Quelle est la différence entre Invoke et DynamicInvoke dans les délégués? Veuillez me donner un exemple de code qui explique la différence entre ces deux méthodes.
Lorsque vous avez une instance de délégué, vous pouvez connaître le type exact ou simplement savoir qu'il s'agit d'un fichier Delegate
. Si vous connaissez le type exact, vous pouvez utiliser Invoke
, ce qui est très rapide - tout est déjà pré-validé. Par exemple:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
Toutefois! Si vous savez juste que c'est le cas Delegate
, il doit résoudre les paramètres, etc. manuellement - cela peut impliquer un déballage, etc. - beaucoup de réflexion est en cours. Par exemple:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Notez que j'ai écrit la args
longue main pour indiquer clairement qu'un object[]
est impliqué. Il y a beaucoup de coûts supplémentaires ici:
MethodInfo
En gros, évitez DynamicInvoke
quand vous le pouvez. Invoke
est toujours préférable, sauf si tout ce que vous avez est un Delegate
et un object[]
.
Pour une comparaison des performances, les éléments suivants en mode version en dehors du débogueur (un exe de console) s'impriment:
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);
Invoke: 0,0478ms, DynamicInvoke: 0,053ms
. Pourquoi les comparez-vous plus d'un appel? Et pourquoi le premier prend plus de temps que le deuxième appel de fonction?