C# Invoke 和 DynamicInvoke 之间的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12858340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:42:31  来源:igfitidea点击:

Difference Between Invoke and DynamicInvoke

c#.netdelegatesinvokedynamic-invoke

提问by testCoder

What is the difference between Invoke and DynamicInvoke in delegates? Please give me some code example which explain difference between that two methods.

委托中的 Invoke 和 DynamicInvoke 有什么区别?请给我一些代码示例来解释这两种方法之间的区别。

采纳答案by Marc Gravell

When you have a delegate instance, you might know the exact type, or you might just know that it is a Delegate. If you know the exact type, you can use Invoke, which is very fast- everything is already pre-validated. For example:

当您有一个委托实例时,您可能知道确切的类型,或者您可能只知道它是一个Delegate. 如果您知道确切的类型,则可以使用Invoke,这非常快- 一切都已经过预先验证。例如:

Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);

However! If you just know that it is Delegate, it has to resolve the parameters etc manually - this might involve unboxing, etc - a lot of reflection is going on. For example:

然而!如果您只知道它是Delegate,它必须手动解析参数等 - 这可能涉及拆箱等 - 正在进行大量反射。例如:

Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);

Note I've written the argslong hand to make it clear that an object[]is involved. There are lots of extra costs here:

请注意,我写了args长篇大论以明确表示object[]涉及an 。这里有很多额外的费用:

  • the array
  • validating the passed arguments are a "fit" for the actual MethodInfo
  • unboxing etc as necessary
  • reflection-invoke
  • then the caller needs to do something to process the return value
  • 数组
  • 验证传递的参数是否“适合”实际 MethodInfo
  • 必要时拆箱等
  • 反射调用
  • 那么调用者需要做一些事情来处理返回值

Basically, avoid DynamicInvokewhen-ever you can. Invokeis always preferable, unless all you have is a Delegateand an object[].

基本上,尽可能避免DynamicInvokeInvoke总是可取的,除非你只有一个Delegate和一个object[]

For a performance comparison, the following in release mode outside of the debugger (a console exe) prints:

为了进行性能比较,在调试器(控制台 exe)之外的发布模式下打印以下内容:

Invoke: 19ms
DynamicInvoke: 3813ms

Code:

代码:

Func<int,int> twice = x => x * 2;
const int LOOP = 5000000; // 5M
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
    twice.Invoke(3);
}
watch.Stop();
Console.WriteLine("Invoke: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
    twice.DynamicInvoke(3);
}
watch.Stop();
Console.WriteLine("DynamicInvoke: {0}ms", watch.ElapsedMilliseconds);