Was ist der Unterschied zwischen Invoke und DynamicInvoke bei Delegierten? Bitte geben Sie mir ein Codebeispiel, das den Unterschied zwischen diesen beiden Methoden erklärt.
Wenn Sie eine Delegateninstanz haben, kennen Sie möglicherweise den genauen Typ oder wissen nur, dass es sich um eine handelt Delegate
. Wenn Sie den genauen Typ kennen, können Sie ihn verwenden Invoke
, was sehr schnell geht - alles ist bereits vorab validiert. Beispielsweise:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
Jedoch! Wenn Sie nur wissen, dass Delegate
dies der Fall ist, müssen die Parameter usw. manuell aufgelöst werden - dies kann das Auspacken usw. beinhalten - es wird viel nachgedacht. Beispielsweise:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Hinweis: Ich habe die args
lange Hand geschrieben, um zu verdeutlichen, dass es sich um eine object[]
handelt. Hier fallen viele zusätzliche Kosten an:
MethodInfo
Vermeiden DynamicInvoke
Sie grundsätzlich, wann immer Sie können. Invoke
ist immer vorzuziehen, es sei denn, Sie haben nur ein Delegate
und einobject[]
.
Für einen Leistungsvergleich wird im Release-Modus außerhalb des Debuggers (einer Konsolen-Exe) Folgendes gedruckt:
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
. Warum vergleichen Sie sie mehr als 1 Anruf? Und warum dauert der erste länger als der zweite Funktionsaufruf?