与标签文本异步

本文关键字:异步 文本 标签 | 更新日期: 2023-09-27 18:03:09

我有一个按钮,当我点击它时,我希望它用值

更新UI

this is my button

       private async void Button_Click(object sender, RoutedEventArgs e)
       {
        await DoItAsync();
       }

,这是DoIt!

    public async Task DoSomethingAsync()
    {
       await Task.Run(()=>{
            for(int i = 0; i < 2000; i++)
            {
               //labelName.Content = i.ToString();
               Console.WriteLine(i);
            }
        });
    }

所以如果我运行上面的代码,点击我的按钮,DoItAysnc被调用,所有的数字都显示在控制台中。

如果取消注释

labelName.Content = i.ToString(); 

我得到一个异常,实际上如下:调用线程不能访问这个对象,因为它是另一个线程拥有的。

我知道Async和await不能为你解决线程问题,但我确实认为这会起作用。我想知道如何得到这个工作,使UI更新为每个I值没有UI变得无响应。

任何关于这方面的好资源也会很有帮助。

一如既往,kinds regards

与标签文本异步

在这个特定的例子中,您所做的一切似乎都是在标签中尽可能快地计数到2000。这不太可能是您的实际用例。

如果你想在多个不同的异步操作之间更新UI(例如,该操作只是等待一段时间),那么你可以这样组织你的代码:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 2000; i++)
    {
        await Task.Delay(TimeSpan.FromSeconds(1));
        labelName.Content = i.ToString();
    }
}

如果你在概念上做的是用一个长时间运行的非UI操作的进程来更新UI,那么Progress类是专门用来处理这个问题的:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    Progress<int> progress = new Progress<int>(
        i => labelName.Content = i.ToString());
    await Task.Run(() => DoWork(progress));
}
private void DoWork(IProgress<int> progress)
{
    for (int i = 0; i < 2000; i++)
    {
        //Do Stuff
        progress.Report(i);
    }
}

一般来说,第一个选项是有意义的,如果你可以把你的问题分解成一组小的异步操作,其中每个操作之间更新UI。第二种方法是,如果存在一个长时间的非ui操作,且该操作不容易分解为更小的操作。

看看这里的答案。不管你如何启动你的工作线程(Thread。首先,任务。运行,BackgroundWorker.RunWorkerAsync),你不能影响UI的变化,除非你在UI线程上运行。

正如@t-mckeown所说,解决方案是强行进入UI线程。如何做到这一点取决于技术(WFP=Dispatcher, WinForms= invokerrequired_begininvoke)。