之间的调用和DynamicInvoke差异 [英] Difference Between Invoke and DynamicInvoke

查看:222
本文介绍了之间的调用和DynamicInvoke差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在代表调用和DynamicInvoke之间的区别是什么?请给我一些code例子解释说,这两种方法之间的差异。

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

推荐答案

当你有一个委托实例,你可能知道确切的类型,或者你可能只知道它是一个代理。如果你知道确切的类型,你可以使用调用,这是非常快 - 一切都已经pre-验证。例如:

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:

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 slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);

请注意我已经写了的args 长的手说清楚,一个 [对象] 参与。还有很多额外的费用在这里:

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

  • 阵列
  • 验证传递的参数是一个适合的实际的MethodInfo
  • 在拆箱等必要
  • 反射调用
  • 则调用者需要做一些事来处理返回值
  • 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

基本上避免 DynamicInvoke 时的一次即可。 调用总是preferable,除非你已经是一个代理对象[]

Basically, avoid DynamicInvoke when-ever you can. Invoke is always preferable, unless all you have is a Delegate and an object[].

有关的性能比较,调试器(控制台EXE)打印之外以下在释放模式:

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

Invoke: 19ms
DynamicInvoke: 3813ms

code:

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);

这篇关于之间的调用和DynamicInvoke差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆