5

Ich versuche, über SynchronizationContext und Freunde zu lernen. Wenn ich einen benutzerdefinierten Synchronisationskontext am Anfang von z. eine Konsolen-App Unter welchen Bedingungen fließt der aktuelle Synchronisationskontext mit meinen asynchronen Operationen? Gibt es Unterschiede zwischen Task und anderen, z.B. Delegate.BeginInvoke?SynchronizationContext, wann fließt es und wann nicht?

void Main() 
{ 
    SynchronizationContext.SetSynchronizationContext(new FooContext()); 
    Action a =() => 
    { 
     var current = SynchronizationContext.Current; 
     //current is null here 
    }; 
    a.BeginInvoke(null,null); 

    ...sleep 

Wenn ich Sachen auf dem Thread-Pool auszuführen, bin ich ein Synchronisationskontext zu diesem bestimmten Thread zuzuordnen gezwungen, die zur Zeit meiner Arbeit ausgeführt wird?

+1

Werfen Sie einen Blick auf diesen Artikel http://msdn.microsoft.com/en-us/magazine/gg598924.aspx. Aber ein Problem ist, dass anderer Code wählen kann, den SynchronizationContext zu stoppen, indem er ".ConfigureAwait (false)" aufruft. In der Tat ist es die beste Vorgehensweise für Nicht-UI-Bibliotheken, dies zu tun, da sie sich nicht darum kümmern, dass, wenn "Auf Wiedersehen" in demselben Thread erwartet wird, sie gestartet wurde. –

+1

Es ist eine unglaublich breite Frage. Die einzige Methode, mit der Sie dabei herauskommen, ist das Verlernen, dass die BeginInvoke() - Methode eines Delegates * alles * mit SynchronizationContext zu tun hat."BeginInvoke" ist nur ein generischer Name für "Code asynchron ausführen". SynchronizationContext hat nur etwas damit zu tun, die Art von Problemen zu lösen, auf die Sie stoßen, wenn Sie das tun. –

+0

Vielleicht beantworten Sie eine Erklärung, warum es zu breit ist? Viele Dokumente da draußen glauben, dass der Synchronisationskontext mit dem Ausführungskontext zwischen asynchronen Operationen fließt. Wie im obigen Beispiel fließt der logische Aufrufkontext, aber nicht der Synchronisationskontext. Hinweise darauf, warum dies der Fall ist, wären interessant. –

Antwort

4

Unter welchen Bedingungen fließt der aktuelle Synchronisationskontext mit meinen asynchronen Operationen?

Wenn eine async Methode ein await ausführt, wird standardmäßig einen aktuellen Kontext erfassen und dass die async Methode zur Wiederaufnahme verwenden. Dieser Kontext ist SynchronizationContext.Current, es sei denn, es ist null, in diesem Fall ist es TaskScheduler.Current. Ich beschreibe dieses Verhalten in meinem async intro blog post, meinem MSDN article on SynchronizationContext, und meinem MSDN article on async best practices.

Gibt es Unterschiede zwischen Task und anderen, z. Delegierter.BeginnInvozieren?

Dieses Verhalten ist einzigartig für async und await. Delegate.BeginInvoke bedeutet "diesen Delegaten für einen Thread-Pool-Thread ausführen", so dass es die SynchronizationContext nicht weitergibt. Weder tun modernere Ansätze wie Task.Run.

Wenn ich Sachen auf dem Thread-Pool ausführen, bin ich gezwungen, einen Synchronisierungskontext diesem bestimmten Thread zuzuweisen, der gerade meine Arbeit ausführt?

Im Allgemeinen sollten Sie keinen Synchronisationskontext für einen Thread installieren, den Sie nicht besitzen. Wenn Sie einen Thread in einem Threadpool platzieren, sollte er entfernt werden, bevor der Thread an den Threadpool zurückgegeben wird. Wenn Sie einen Synchronisationskontext installieren, sollten Sie den Thread wahrscheinlich nie zurückgeben (ein benutzerdefinierter Synchronisationskontext wird normalerweise mit einer "Hauptschleife" für diesen Thread assoziiert).

Im obigen Beispiel fließt der logische Aufrufkontext, jedoch kein Synchronisationskontext. Hinweise darauf, warum dies der Fall ist, wären interessant.

Die anderen Kontexte sind noch weniger dokumentiert. Stephen Toub hat die definitive post on the subject. Im Wesentlichen müssen einige Daten wie Sicherheit fließen; die meisten anderen Daten nicht.

Verwandte Themen