2016-04-25 5 views
1

Ok, ich bin ein wenig verwirrt hier. Gehen Sie über Code in Bezug auf die SynchronzationContext, speziell bei der Verwendung in WPF so ist es eigentlich ein DispatcherSynchronizationContext. Im Folgenden ein Auszug aus MSDN Magazinen zu dieser Klasse:Wie erhalten Sie den aktuellen SynchronizationContext für ein bestimmtes WPF-Fenster?

DispatcherSynchronizationContext (WindowsBase.dll: System.Windows.Threading) WPF und Silverlight-Anwendungen verwenden, um eine DispatcherSynchronizationContext, die Delegierten auf den UI-Thread Dispatcher mit „Normal“ Prioritätswarteschlangen . Dieser SynchronizationContext wird als aktueller Kontext installiert, wenn ein Thread seine Dispatcher-Schleife aufruft, indem er Dispatcher.Run aufruft. Der Kontext für DispatcherSynchronizationContext ist ein einzelner UI-Thread.

Alle in den DispatcherSynchronizationContext eingereihten Delegierten werden nacheinander von einem bestimmten UI-Thread in der Reihenfolge ausgeführt, in der sie in die Warteschlange gestellt wurden. Die aktuelle Implementierung erstellt einen DispatcherSynchronizationContext für jedes Fenster der obersten Ebene, auch wenn sie alle den gleichen zugrunde liegenden Dispatcher teilen.

(Von hier aus: https://msdn.microsoft.com/magazine/gg598924.aspx)

Was ich verwirrt die beiden Teile, die ich bolded/kursiv geschrieben scheinen im Widerspruch zueinander zu sein. Die erste besagt, dass eine DispatcherSynchronizationContext pro Thread erstellt und als aktueller Sync-Kontext des Threads festgelegt wird. Im zweiten Auszug wird jedoch ein DispatcherSynchronizationContextpro Fenster erstellt, auch wenn sie alle den gleichen Dispatcher/UI-Thread teilen.

Was vermisse ich/verstehe ich nicht?

Und wenn es wirklich eine pro Fenster ist, nicht nur pro Thread, wie erhalten Sie die DispatcherSynchronizationContext für ein bestimmtes Fenster?

Antwort

1

In WPF ist die SynchronizationContext im Wesentlichen ein Wrapper für den Dispatcher. Wenn Sie sich die Implementierung here ansehen, können Sie sehen, dass die Post und Send Methoden Invoke und BeginInvoke wrap.

Was die Dokumentation bezieht sich auf die DispatcherSynchronizationContext in Bezug auf ist, dass es den aktuellen UI-Thread ist greifen die Arbeit zu tun, das heißt, mit

Application.Current.Dispatcher 

während SyncrhonizationContext tatsächlich die aktuellen Threads Dispatcher verwenden, unabhängig von whethere es ist UI verwandt oder nicht.

Thread.CurrentContext 

Da alle Windows auf dem UI-Thread ausgeführt werden, gibt es keine Möglichkeit, eine bestimmte DispatcherSynchronizationContext für jeden zu bekommen.

+0

greifen kann ich verstehen, dass es den Disponenten hüllt , aber ich frage mich, ob das der Fall ist, warum würden sie für jedes Fenster eines erstellen? Was wäre der Sinn, im Gegensatz zu nur einem pro Disponent? Und noch einmal, wenn es ein Fenster pro Fenster gibt, welches wird in die aktuelle Eigenschaft des Threads gesetzt, wenn der Dispatcher gemäß der von mir zitierten Dokumentation startet? Ist es nur der erste geschaffen? – MarqueIV

0

Alle UI-Anwendungen (wie WinForms und WPF) haben spezielle UI-Threads (für das aktuelle Window) und SynchronzationContext.Post (die für den Fall übersetzen, dass WPF - in Dispatcher.BeginInvoke übersetzt) ​​sended delegate als Parameter in die UI-Thread-Warteschlange für aktuelles Fenster. Also - jedes Fenster hat eigenen SynchronizationContext, aber im Thread können Sie verschiedene SynchronizationContext verwenden.

Und einen Punkt mehr - jeder Thread haben ExecutionContext, aber nur UI-Threads haben SynchronzationContext (in anderen - zum Beispiel von CLR ThredPool - SynchronzationContext = null). Und wenn Sie Kontext erfassen:

ExecutionContext ec = ExecutionContext.Capture(); 

innen ExecutionContext werden Sie SynchronzationContext haben, so

Thread.CurrentContext 

es geht um ExecutionContext, SynchronzationContext Sie von

var sc = SynchronizationContext.Current;