Most of the classes in WPF enforce thread affinity. If you are developing a multi-threaded application, you must make sure that the visual elements of your application are only accessed on the UI thread. Generally, this means finding "the Dispatcher" and pushing whatever work you require onto its queue.
There are many ways to find "the Dispatcher"; your approach will depend on the complexity of your application and the purity of your architecture:
- Brute force: Provided you aren't playing any games with multiple AppDomains, Application.Current.Dispatcher will give you the reference you need.
- View access: All WPF visual elements derive from DispatcherObject. If you have access to a visual element, you can inspect its Dispatcher property.
- Saving for later: During application startup, if you can guarantee that you are running on the UI thread, store a reference to Dispatcher.CurrentDispatcher for later use while your view models are being initialized.
There are two methods on Dispatcher that queue up new work: BeginInvoke() and Invoke(). BeginInvoke() operates asynchronously, has fewer overloads to wade through, and gives you control over operation cancellation and reprioritization. Invoke() operates synchronously, has twice as many overloads due to extra TimeSpan arguments, and effectively freezes any progress on the thread making the call. While there are cases where Invoke() may be more appropriate, BeginInvoke() supersets its functionality and is more often the superior choice.
[Deadmau5: A City in Florida -- YouTube]
References
- MSDN: WPF Architecture
- MSDN: WPF Threading Model
No comments:
Post a Comment