2013-06-04 10 views
16

Ich lerne immer noch das gesamte Task-Konzept und TPL. Nach meinem derzeitigen Verständnis werden die SynchronizationContext-Funktionen (falls vorhanden) von await verwendet, um die Aufgabe "irgendwo" zu versenden. Auf der anderen Seite verwenden die Funktionen in der Task Klasse nicht den Kontext, richtig?Wie Sie eine Aufgabe erhalten, die SynchronizationContext verwendet? Und wie wird SynchronizationContext überhaupt verwendet?

So zum Beispiel Task.Run(...) wird immer die Aktion auf einem Worker-Thread des Thread-Pools und ignorieren Sie die SynchronizationContext.Current vollständig. await Foobar() würde den Kontext verwenden, um die generierte Aufgabe nach der await?

Wenn das stimmt, ist meine Frage: Wie kann ich eine Task erhalten, die tatsächlich eine Aktion ausführt, aber mit SynchronizationContext.Current.Send/Post?

Und kann jemand eine gute Einführung in SynchronizationContext empfehlen, insbesondere wann und wie sie vom Rest des Frameworks verwendet werden? Die MSDN scheint sehr leise über die Klasse zu sein. Die Top-Google-Treffer (here und here) scheinen nur auf das Senden von Windows Forms zugeschnitten zu sein. Stephen Cleary schrieb an article, was schön ist zu lernen, welche Kontexte bereits existieren und wie sie funktionieren, aber ich habe kein Verständnis dafür, wo und wann sie tatsächlich verwendet werden.

Antwort

26

Wie erhalte ich eine neue Aufgabe, dass tatsächlich eine Aktion läuft aber abgesendet wird SynchronizationContext.Current.Send/Post mit?

Verwenden Sie spezielle Aufgabenplaner:

Task.Factory.StartNew(
    () => {}, // this will use current synchronization context 
    CancellationToken.None, 
    TaskCreationOptions.None, 
    TaskScheduler.FromCurrentSynchronizationContext()); 

Und kann eine gute Einführung in SynchronizationContext

Blick auf den Artikel It's All About the SynchronizationContext von Stephen Cleary jedem empfehlen.

+0

ah, schön. Vielen Dank. Gibt es einen Unterschied zwischen "Task.Run" und "Task.Factory.StartNew"? (Ich meine .. jeden anderen Unterschied als das "' Task.Factory.StartNew' akzeptieren einige Parameter, die 'Task.Run' nicht";)) – Imi

+0

Nein, es gibt keinen anderen Unterschied zwischen ihnen. – Dennis

+0

_Look in diesem Artikel._ Vielen Dank für den Link. Ich habe diesen Artikel bereits gelesen und ihn in meiner Frage verlinkt - sehr gut, um zu verstehen, welche Kontexte existieren und warum sie überhaupt eingeführt wurden. Irgendwelche anderen guten Quellen, vielleicht im Detail darüber, welche Klasse die Kontexte wann verwendet? Oder gehe ich falsch an die TPL heran und lese "Warum sollte ich mich eigentlich nie darum kümmern"? : D. – Imi

18

Wie Sie dies zu lernen, ist es wichtig, darauf hinzuweisen, dass Taskwie von der TPL verwendet ganz anders ist als Taskwie async verwendet/erwarten, obwohl sie die gleiche Art sind. Zum Beispiel verwendet TPL häufig übergeordnete/untergeordnete Aufgaben, aber async/await nicht.

TPL verwendet Aufgabenplaner, um seine Aufgaben auszuführen. Wie Dennis darauf hingewiesen hat, gibt Ihnen TaskScheduler.FromCurrentSynchronizationContext einen Taskplaner, der Post auf dem aktuellen SynchronizationContext verwendet, um seine Aufgabe auszuführen.

async/await verwendet in der Regel keine Aufgabenplaner. Ich habe eine Einführung async/await post auf meinem Blog, die Kontextinformationen enthält, und ich erwähne es auch kurz in meinem MSDN article (es ist jedoch leicht zu übersehen, obwohl). Im Wesentlichen, wenn eine async Methode bei einer await aussetzt, wird standardmäßig die aktuelle SynchronizationContext erfasst (es sei denn, es ist null, in diesem Fall wird es die aktuelle TaskScheduler erfassen). Wenn die async-Methode fortgesetzt wird, wird die Ausführung in diesem Kontext fortgesetzt.

Dennis wies auf die TPL Art und Weise eine Aufgabe an die aktuellen SynchronizationContext der Planung, aber in async/await Welt, dieser Ansatz ist nicht erforderlich. Vielmehr können Sie explizit über Task.Run Aufgaben an den Threadpool planen:

async Task MyMethodAsync() 
{ 
    // Whee, on a SynchronizationContext here! 
    await Task.Run(() => { }); // Ooo, on the thread pool! 
    // Back on the SynchronizationContext ... 
    // ... automagically! 
} 

ich meine SynchronizationContext Artikel genau geschrieben, weil die MSDN-Dokumentation so fehlten. Ich habe eine little more information on my blog, aber alle wichtigen Bits sind im MSDN-Artikel. Viele Typen verwenden AsyncOperation statt SynchronizationContext direkt; Die beste Dokumentation dafür ist buried under the EAP docs (section "Threading and Context"). Aber ich sollte auch darauf hinweisen, dass EAP effektiv veraltet ist aufgrund async/await, so würde ich keinen Code schreiben mit AsyncOperation (oder SynchronizationContext) - es sei denn, ich war eigentlich mein eigenes SchreibenSynchronizationContext.

+0

_SynchronizationContext (es sei denn es ist null, in diesem Fall wird es den aktuellen TaskScheduler erfassen) ._ Interessant ... Eigentlich, wenn ich auf TaskScheduler's nachlese, fange ich an zu denken, dass ein TaskScheduler - kein SynchronizationContext - was ich für meinen brauche ursprüngliches Problem (hier nicht beschrieben). Haben Sie gute Referenzen von TaskScheduler vs. SynchronizationContexts und was ist der Unterschied? (Von MSDN aus betrachtet scheinen beide für das Verteilen von Aufgaben auf Threads verantwortlich zu sein, oder?) – Imi

+0

'SynchronizationContext' wurde mit .NET 2.0 entwickelt und wird verwendet, um Delegierte (synchron oder asynchron) zu planen. 'TaskScheduler' wurde in .NET 4.0 eingeführt und wird verwendet, um Aufgaben (asynchron) zu planen. –