与标签文本异步

Jam*_*mes 0 .net c# user-interface async-await

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

这是我的按钮

       private async void Button_Click(object sender, RoutedEventArgs e)
       {
        await DoItAsync();
       }
Run Code Online (Sandbox Code Playgroud)

这就是DoIt!

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

        });
    }
Run Code Online (Sandbox Code Playgroud)

因此,如果我运行上面的代码,单击我的按钮,调用DoItAysnc并在控制台中显示所有数字.

如果我不发表评论

labelName.Content = i.ToString(); 
Run Code Online (Sandbox Code Playgroud)

我得到一个异常,事实如下:调用线程无法访问此对象,因为另一个线程拥有它.

我知道Async和await不会为你解决线程问题,但我确实认为这会有效.我想知道如何使其工作,以便为每个i值更新UI,而不会使UI无响应.

对此有任何好的资源也会有所帮助.

各种各样的问候

Ser*_*rvy 8

在这种特殊情况下,你所做的一切似乎都是尽可能快地在标签上计算到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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您在概念上正在做的是使用长时间运行的非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);
    }
}
Run Code Online (Sandbox Code Playgroud)

通常,如果您可以将问题分解为一组小的异步操作,其中UI在每个操作之间进行更新,则第一个选项是有意义的.如果存在单个长的非UI操作而不能轻易地分解为较小的操作,则完成第二种方法.