从task \ thread中的代码更改ui值

时间:2018-05-25 17:09:54

标签: c# wpf xaml

在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++;
            }
        });
}

输出:标签保持不变

1 个答案:

答案 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参数来确定您调用的所有操作的运行优先级。