7 Stimmen

Leistungskosten bei Verwendung der IAsyncResult-Überladung von Task.FromAsync

Ich versuche, einige bestehende APM-Aufrufe zu verpacken ( BeginX , EndX ) in Tasks um in den Genuss aller Vorteile zu kommen. Leider sind unsere Methoden unkonventionell und verwenden out Parameter und kann daher nicht die Standard FromAsync Methode, bei der Sie ihm sowohl den Anfangs- als auch den Enddelegierten geben und ihn schön einpacken lassen.

Dieser Artikel beschreibt die Alternative: eine Überladung, die eine IAsyncResult und erfordert nur die Implementierung des End-Callbacks. Sie nehmen die IAsyncResult Handle, warten Sie dann, bis es abgeschlossen ist, und rufen Sie dann den Delegaten auf, den Sie übergeben haben.

Das schien in Ordnung zu sein, aber dann las ich ein weiterer Artikel über das Einbinden von APM-Aufrufen in Aufgaben . Er erwähnt auch, dass die IAsyncResult Überlastung ist nicht so effizient wie die anderen Methoden. Es scheint mir, dass dies bedeutet, dass der Rückruf nicht verwendet wird, um den Abschluss der Methode zu melden. Das bedeutet, dass sie die AsyncWaitHandle oder Umfragen IsCompleted . Welches verwenden sie? Wie hoch ist der Leistungsverlust?

Wenn es eine Abfrage durchführt, bedeutet dies, dass der Rückruf möglicherweise nicht sofort erfolgt und die Mitarbeiter während des gesamten Gesprächs damit beschäftigt sind, die Daten zu überprüfen. Wenn sie einen AsyncWaitHandle Wenn ich eine asynchrone Methode verwende, gibt es einen weiteren Thread, der auf das Ergebnis wartet, was für mich den Sinn einer asynchronen Methode völlig zunichte macht.

Weiß jemand, was sie tun und wie schwerwiegend diese Leistungseinbußen sind?

1voto

Chris Shain Punkte 49991

Wenn man sich den Code in JustDecompile ansieht, wird eine TaskCompletionSource erstellt, die das IAsyncObject umhüllt, wodurch ein neuer Task erstellt wird, was wahrscheinlich bedeutet, dass ein Thread auf die Fertigstellung des IAsyncObjects wartet. Nicht ideal, aber es ist wahrscheinlich der einzige Weg, es zu tun, da es keine Möglichkeit gibt, eine gute one-size-fits-all Polling-Rate zu machen.

1voto

Reed Copsey Punkte 536986

Weiß jemand, was sie tun und wie schwerwiegend diese Leistungseinbußen sind?

Es ist nicht unglaublich schwer, aber es gibt mehr Aufwand. Da Sie ihnen nicht die gleichen Informationen zur Verfügung stellen (nur die IAsyncResult ), muss die Implementierung den Aufruf ThreadPool.RegisterWaitForSingleObject um einen Rückruf auszulösen, wenn die IAsyncResult komplettiert.

Wenn dies nicht verwendet wird und das Paar Begin/End + Callback vorhanden ist, kann der Callback automatisch den Abschluss der Aufgabe auslösen, wodurch der zusätzliche Warteaufruf hier entfällt. Dies bindet einen ThreadPool-Thread, der das Wartehandle blockiert (WaitOne), bis der Vorgang abgeschlossen ist. Wenn dies nur selten vorkommt, ist der Leistungsmehraufwand wahrscheinlich vernachlässigbar, aber wenn Sie dies öfters tun Los könnte dies problematisch sein.

0voto

jyoung Punkte 4963

Wenn Sie ein ISyncResult übergeben, gibt es für die TaskFactory keine Möglichkeit, einen Callback zurückzuschicken. Die TaskFactory braucht also das ISynResult, um ein WaitHandle zu erzeugen, und braucht den ThreadPool, um einen Thread zu erhalten, der auf dieses Handle wartet. Es ist kein Polling beteiligt.

0voto

Benjol Punkte 60397

Ich bin hierher gekommen, weil ich ein ähnliches Problem hatte (mit out Parameter), sondern nur auf der End Methode. Das habe ich mir ausgedacht, vielleicht hilft es ja jemandem:

var provider = new Provider();
return Task<Whatever>.Factory.FromAsync(provider.Begin, ar =>
{
    Whatever outparam;
    provider.End(out outparam);
    return outparam;
}, state);

Es kompiliert :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X