在wpf中假设我有一个计数器标签,在后面的代码中我试图每隔3秒增加一次值,但它不起作用,我的意思是:
XAML:
<Label x:Name="MyLabel" Content="Label" />
代码背后:
public MyClass()
{
Task t = Task.Factory.StartNew(() =>
{
int i = 1;
while (true)
{
MyLabel.Content=i;
Thread.Sleep(3000);
i++;
}
});
}
输出:标签保持不变
答案 0 :(得分:1)
WPF UIElement只能在一个线程中访问。因此,您无法访问或修改<Label/>
。
但WPF还提供了一个名为Dispatcher
的线程模型,您可以获取UIElement的Dispatcher
并将您的操作调用到原始线程中。
您应该做的是将MyLabel.Content=i
更改为MyLabel.Dispatcher.InvokeAsync(() => MyLabel.Content = i);
。
这是整个代码:
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++;
}
});
我将同步调用更改为异步调用,建议这样做。
当您尝试在后台线程中更新UI时,您会发现Dispatcher.InvokeAsync
非常有用。此外,您可以添加DispatcherPriority
参数来确定您调用的所有操作的运行优先级。