Why use Dispatcher.BeginInvoke?
I have seen (and read) about using Dispatcher.BeginInvoke to ensure that UI updates occur on the UI thread. I understand thi开发者_JAVA技巧s reasoning.
But I have seen examples where in the view code-behind, assigning properties, such as the Text property for a TextBlock, is declared to be safe only if you assign it in this Dispatcher.BeginInvoke.
Question If I'm manipulating anything from a view's code-behind, isn't it implied that it's being manipulated on the UI thread (assuming I'm not using a BackgroundWorker or an asynchronous service call).
In the examples I mentioned above, there are no other threads or async operations used.
Question 2 If I have an async web service handler, and I want to update the string of a TextBlock from within this handler. Can I directly assign the Text property of the TB, or should I use a Dispatcher.BeginInvoke. Note that I wouldn't do this normally as I favor data binding over direct UI element manipulations like this.
You ask "isn't it implied that it's being manipulated on the UI thread". There isn't anything giving an absolute guarantee, as Mike points out non-private code entry points could possibly be called on a non UI Thread.
However you can be sure that event arriving from UI elements will be on the UI thread.
As to taking any precautionary action to ensure your code-behind runs on the UI thread, I don't think that is sensible. What happens if you just let code proceed normally. Possibly it succeeds because you don't actually interact with UI element, no harm done. Alternatively code proceeds and throws an exception. Is that bad?
Using a precautionary BeginInvoke
results in the calling code completing asynchronously with UI manipulation code that was invoked. This can have unpredicatable result that can be a nightmare to track down. Its much better to have your code behave predictably. Simply throw an error back at the code that ought take responsibility for calling a UI component on the correct thread. After all code-behind is running as part of UI component such as a UserControl
or a Page
.
Consider also that existing UI elements in the Runtime, SDK and toolkit don't do precautionary thread switching.
Edit: answer to the cheeky addition of a secondary question
That depends on the Async API you are using and what thread the API was called on.
When you invoke a WebClient
async method from the UI Thread then the corresponding Event is raised on the UI Thread as well. Similarly if you are using a WCF service Client class the Completed event will be raised on the UI Thread if the async operation is initially invoked on the UI Thread.
However when using the Begin/End pairs on the WebRequest component (or the standard service interface from WCF) then the callbacks will run on a background thread regardless of the original thread used to start the operation.
If it's a protected method or event handler that is only responding to UI events, then you should be safe without a dispatcher. If you're in code that can be externally exposed in any way, however, you are better off not making any assumptions about what thread it might execute on.
精彩评论