WPF UIElement can only be accessed in a single Thread. So you cannot access or modify the value of the <Label/>
.
But WPF also provides a thread model named Dispatcher
, you can get the Dispatcher
of the UIElement and invoke your action into the original thread.
What you should do is to change MyLabel.Content=i
into MyLabel.Dispatcher.InvokeAsync(() => MyLabel.Content = i);
.
This is the whole code:
Task.Run(async () =>
{
int i = 1;
while (true)
{
// Note: this works because the thread slept 3000ms.
// If the thread doesn't sleep, we should declare a new variable
// so that i will not change when the action invokes.
// That means `var content = i;`
// Then `MyLabel.Dispatcher.InvokeAsync(() => MyLabel.Content = content);`
await MyLabel.Dispatcher.InvokeAsync(() => MyLabel.Content = i);
await Task.Delay(3000);
i++;
}
});
I change your synchronized call to async call and this is recommended.
You'll find that Dispatcher.InvokeAsync
is very useful when you're trying to update UI in the background thread. Furthermore, you can add DispatcherPriority
parameter to determine the running priority of all the actions you invoked.