Diferença entre Invoke e DynamicInvoke

Qual é a diferença entre Invoke e DynamicInvoke em delegates? Por favor me dê algum exemplo de código que explique a diferença entre esses dois methods.

Quando você tem uma instância delegada, você pode saber o tipo exato, ou você pode apenas saber que é um Delegate . Se você sabe o tipo exato, você pode usar o Invoke , que é muito rápido – tudo já está pré-validado. Por exemplo:

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

Contudo! Se você apenas sabe que é Delegate , ele tem que resolver os parâmetros etc manualmente – isso pode envolver unboxing, etc – muita reflection está acontecendo. Por exemplo:

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

Observe que escrevi o ponteiro longo de args para deixar claro que um object[] está envolvido. Há muitos custos extras aqui:

  • o array
  • validar os argumentos passados ​​é um “ajuste” para o MethodInfo real
  • unboxing etc, conforme necessário
  • reflection-invocação
  • então o chamador precisa fazer algo para processar o valor de retorno

Basicamente, evite o DynamicInvoke sempre que puder. Invoke é sempre preferível, a menos que você tenha um Delegate e um object[] .

Para uma comparação de desempenho, o seguinte no modo de lançamento fora do depurador (um exe do console) imprime:

 Invoke: 19ms DynamicInvoke: 3813ms 

Código:

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