Update WPF controls at run time

2019-07-01 10:56发布

问题:

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.