I'm trying to write a WPF application that will update a set of text boxes and labels at run time using threads but the problem is that when ever a thread tries to update the text boxes and labels I get the following error: "The calling thread cannot access this object because a different thread owns it." Is it possible to update the control at run time?
问题:
回答1:
Yes, but you have to update the UI elements in the UI thread using Dispatcher.Invoke.
Example in C#: Instead of
myTextBox.Text = myText;
use
Dispatcher.Invoke(new Action(() => myTextBox.Text = myText));
VB.NET (before version 4) does not support anonymous methods, so you'll have to workaround it with an anonymous function:
Dispatcher.Invoke(Function() UpdateMyTextBox(myText))
...
Function UpdateMyTextBox(ByVal text As String) As Object
myTextBox.Text = text
Return Nothing
End Function
Alternatively, you can start your background threads using the BackgroundWorker class, which support updates in the UI through the ProgressChanged
and RunWorkerCompleted
events: Both events are raised in the UI thread automatically. An example for using BackgroundWorker can be found here: SO question 1754827.
回答2:
Controls in WPF have a Dispatcher
property on which you can call Invoke
, passing a delegate with the code you'd like to execute in the context of the GUI thread.
myCheckBox.Dispatcher.Invoke(DispatcherPriority.Normal,
() => myCheckBox.IsChecked = true);
回答3:
For a thorough explanation of the WPF threading model, including how the Dispatcher works, jump to minute 17 in this video from the Hiking Mount Avalon workshop at Mix09.