AFAIK, alles was es weiß ist, dass irgendwann seine SetResult
oder SetException
Methode aufgerufen wird, um die Task<T>
Belichtung durch seine Task
Eigenschaft zu vervollständigen .
Mit anderen Worten, es fungiert als Produzent für a Task<TResult>
und dessen Fertigstellung.
Ich habe hier das Beispiel gesehen:
Wenn ich eine Möglichkeit brauche, eine Func asynchron auszuführen und eine Aufgabe zu haben, um diese Operation darzustellen.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Welche verwendet * werden könnte , wenn ich nicht Task.Factory.StartNew
- aber ich tun haben Task.Factory.StartNew
.
Frage:
Kann jemand ein Szenario mit gutem Beispiel erklären Sie sich bitte im Zusammenhang direkt an TaskCompletionSource
und nicht auf eine hypothetische Situation , in der ich nicht habe Task.Factory.StartNew
?
quelle
Antworten:
Ich verwende es meistens, wenn nur eine ereignisbasierte API verfügbar ist ( z. B. Windows Phone 8-Sockets ):
Daher ist es besonders nützlich, wenn es zusammen mit dem
async
Schlüsselwort C # 5 verwendet wird .quelle
SomeApiWrapper
Ist es so, dass irgendwo darauf gewartet wird, bis der Herausgeber das Ereignis auslöst, das dazu führt, dass diese Aufgabe abgeschlossen wird?Microsoft.Bcl.Async
Paket auf NuGet veröffentlicht, das dieasync/await
Schlüsselwörter in .NET 4.0-Projekten zulässt (VS2012 und höher wird empfohlen).Nach meinen Erfahrungen
TaskCompletionSource
eignet es sich hervorragend, um alte asynchrone Muster in das moderneasync/await
Muster zu verpacken .Das nützlichste Beispiel, an das ich denken kann, ist die Arbeit mit
Socket
. Es hat die alten APM- und EAP-Muster, aber nicht dieawaitable Task
Methoden, dieTcpListener
undTcpClient
haben.Ich persönlich habe mehrere Probleme mit der
NetworkStream
Klasse und bevorzuge das RoheSocket
. Da ich dasasync/await
Muster auch liebe , habe ich eine ErweiterungsklasseSocketExtender
erstellt, für die verschiedene Erweiterungsmethoden erstellt werdenSocket
.Alle diese Methoden verwenden
TaskCompletionSource<T>
, um die asynchronen Aufrufe wie folgt zu verpacken:Ich übergebe das
socket
an dieBeginAccept
Methoden, damit der Compiler eine leichte Leistungssteigerung erzielt, ohne den lokalen Parameter hochziehen zu müssen.Dann die Schönheit von allem:
quelle
Begin.. End...
Anweisungen zu verpacken .Für mich ist ein klassisches Szenario für die Verwendung,
TaskCompletionSource
wenn es möglich ist, dass meine Methode nicht unbedingt einen zeitaufwändigen Vorgang ausführen muss. Damit können wir die spezifischen Fälle auswählen, in denen wir einen neuen Thread verwenden möchten.Ein gutes Beispiel hierfür ist die Verwendung eines Caches. Sie können eine
GetResourceAsync
Methode verwenden, die im Cache nach der angeforderten Ressource sucht und sofort (ohne Verwendung eines neuen Threads mithilfe vonTaskCompletionSource
) zurückgibt, wenn die Ressource gefunden wurde. Nur wenn die Ressource nicht gefunden wurde, möchten wir einen neuen Thread verwenden und ihn mit abrufenTask.Run()
.Ein Codebeispiel finden Sie hier: So führen Sie einen Code mithilfe von Tasks unter bestimmten Bedingungen asynchron aus
quelle
Task.FromResult
. Wenn Sie 4.0 verwenden und keinTask.FromResult
TCS haben, schreiben Sie natürlich Ihr eigenesFromResult
.Task.FromResult
ist nur seit .NET 4.5 verfügbar. Davor war dies der Weg, um dieses Verhalten zu erreichen.Task.Run
sich auf 4,5+. Und mein vorheriger Kommentar bezog sich speziell auf .NET 4.0.In diesem Blog-Beitrag beschreibt Levi Botelho, wie Sie mit
TaskCompletionSource
as einen asynchronen Wrapper für einen Prozess schreiben, damit Sie ihn starten und auf seine Beendigung warten können.und seine Verwendung
quelle
Es sieht so aus, als hätte niemand etwas erwähnt, aber ich denke, Unit-Tests können auch als real genug angesehen werden.
Ich finde
TaskCompletionSource
es nützlich, wenn ich eine Abhängigkeit mit einer asynchronen Methode verspotte.Im aktuellen Testprogramm:
In Unit-Tests:
Schließlich scheint diese Verwendung von TaskCompletionSource ein weiterer Fall von "einem Task-Objekt, das keinen Code ausführt" zu sein.
quelle
TaskCompletionSource wird verwendet, um Task- Objekte zu erstellen , die keinen Code ausführen. In realen Szenarien ist TaskCompletionSource ideal für E / A-gebundene Vorgänge. Auf diese Weise erhalten Sie alle Vorteile von Aufgaben (z. B. Rückgabewerte, Fortsetzungen usw.), ohne einen Thread für die Dauer des Vorgangs zu blockieren. Wenn Ihre "Funktion" eine E / A-gebundene Operation ist, wird nicht empfohlen, einen Thread mit einer neuen Aufgabe zu blockieren . Stattdessen können Sie mit TaskCompletionSource eine Slave-Task erstellen, um nur anzuzeigen, wann Ihre E / A-gebundene Operation beendet ist oder Fehler aufweist.
quelle
In diesem Beitrag aus dem Blog "Parallele Programmierung mit .NET" gibt es ein Beispiel aus der Praxis mit einer anständigen Erklärung . Sie sollten es wirklich lesen, aber hier ist trotzdem eine Zusammenfassung.
Der Blog-Beitrag zeigt zwei Implementierungen für:
Die erste gezeigte Implementierung basiert auf
Task<>
und weist zwei Hauptmängel auf. Im zweiten Implementierungsbeitrag werden diese durch die Verwendung gemindertTaskCompletionSource<>
.Hier ist die zweite Implementierung:
quelle
await Task.Delay(millisecondsDelay); action(); return;
oder (in .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Dies mag die Dinge zu stark vereinfachen, aber die TaskCompletion-Quelle ermöglicht es einem, auf ein Ereignis zu warten. Da das tcs.SetResult erst festgelegt wird, wenn das Ereignis eintritt, kann der Aufrufer auf die Aufgabe warten.
Sehen Sie sich dieses Video an, um weitere Einblicke zu erhalten:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
quelle
Ich habe ein reales Szenario verwendet, in dem ich
TaskCompletionSource
eine Download-Warteschlange implementiert habe. In meinem Fall, wenn der Benutzer 100 Downloads startet, möchte ich nicht alle auf einmal auslösen. Anstatt eine geplante Aufgabe zurückzugeben, gebe ich eine angehängte Aufgabe zurückTaskCompletionSource
. Sobald der Download abgeschlossen ist, schließt der Thread, der in der Warteschlange arbeitet, die Aufgabe ab.Das Schlüsselkonzept hier ist, dass ich mich entkopple, wenn ein Client verlangt, dass eine Aufgabe von dem Zeitpunkt an gestartet wird, an dem sie tatsächlich gestartet wird. In diesem Fall, weil ich nicht möchte, dass sich der Client mit dem Ressourcenmanagement befassen muss.
Beachten Sie, dass Sie verwenden können , async / await in .net 4, solange Sie eine C # 5 Compiler (VS 2012+) sehen verwenden hier für weitere Details.
quelle
Ich habe
TaskCompletionSource
eine Aufgabe ausgeführt, bis sie abgebrochen wurde. In diesem Fall handelt es sich um einen ServiceBus-Abonnenten, den ich normalerweise ausführen möchte, solange die Anwendung ausgeführt wird.quelle
TaskCompletionSource
ist zu Aufgaben wieWaitHandle
zu Thread. Und so können wirTaskCompletionSource
eine präzise Signalisierung durchführen .Ein Beispiel ist meine Antwort auf diese Frage: ContentDialog-Verzögerung nach Klicken auf OK
quelle