【问题标题】:Updating UI from the async method从异步方法更新 UI
【发布时间】:2021-04-06 21:50:22
【问题描述】:

我有一个主窗口,上面有一个 TextBlock 和一个 Button 控件,通过单击调用 RunAsync(int) 方法.它正在做一些计算,所以这个过程花费了相当长的时间并阻塞了 UI。我能够将它移动到异步线程,但我完全坚持如何最好地实现在 For 循环的每次迭代中从该方法更新接口。例如,使用进度条。

目前我有以下代码:

public partial class MainWindow : Window
{
    public MainWindow() => InitializeComponent();

    private async Task<List<int>> RunAsync(int par)
    {
        return await Task.Run(() =>
        {
            List<int> list = new List<int>();
            for (int i = 0; i < par;  i++)
            {
                // some code, that takes quite a long time
                Thread.Sleep(500); 
                list.Add(i);
            }
            return list;
        });
    }
    
    private async void StartBtn_Click(object sender, RoutedEventArgs e)
    {
        int count = (await RunAsync(5)).Count;
        label.Text = count.ToString();
    }
}

【问题讨论】:

  • 2 件事:1 而不是 Thread.Sleep... 你应该使用 Task.Delay。 2:使用 Dispatcher 从不同的线程更新 UI
  • ... 或简单地使用绑定...从某个实现 INotyfiPropertyChanged 的​​类中绑定属性并将其实例设置为 MainWindow 的 DataContext ...然后从工作线程更新此属性...就是这样
  • 您甚至可能不需要调用 Dispatcher。只需将异步调用移动到循环体中,即运行并等待异步方法并在每次循环迭代中更新 UI。
  • 您可能想看看Progress&lt;T&gt; 类和how it's used。另一个有用的教程是here
  • 等待线程有一个 SynchronizationContext,所以当 Task.Run 准备好时它会返回到那个线程。无需调用任何东西。

标签: c# wpf asynchronous async-await


【解决方案1】:

如何最好地实现在 For 循环的每次迭代中从此方法更新接口。例如,使用进度条。

这就是IProgress&lt;T&gt; 的用途。

附带说明,如果您使用call methods using Task.Run instead of *implementingthem usingTask.Run`,您会发现您的代码更简洁。

public partial class MainWindow : Window
{
  private List<int> Run(int par, IProgress<int> progress)
  {
    List<int> list = new List<int>();
    for (int i = 0; i < par;  i++)
    {
      // some code, that takes quite a long time
      Thread.Sleep(500); 
      list.Add(i);
      progress?.Report(i);
    }
    return list;
  }
    
  private async void StartBtn_Click(object sender, RoutedEventArgs e)
  {
    var progress = new Progress<int>(report => /* Do something with report */);
    var list = await Task.Run(() => Run(5, progress));
    label.Text = list.Count.ToString();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多