0

我第一次尝试异步等待并遇到使用进度的问题。我使用 await 调用我的异步方法并传入我的进度操作。我想要发生的是显示进度,当方法完成消息说我们“完成!” 被展示。发生的情况是显示进度,“完成!” 显示,然后是最后一条进度消息,这是输出示例:1、2、

完毕!3

似乎异步已返回,并且 UI 上下文在最终进度有机会运行之前执行。我可以通过添加处理程序来克服这个问题,但要正确地遵循模式。

 public async void button1_Click(object sender, EventArgs e)
    {
        await JustDoItAsync(new Progress<int>(ProgressUpdate));

        textBox1.Text += "\r\nDone!\r\n";
    }

    public async Task JustDoItAsync(IProgress<int> progress)
    {
        for (int i = 0; i < 3; i++)
        {
            await Task.Delay(500);
            progress.Report(i + 1);
        }
    }

    private void ProgressUpdate(int step)
    {
        textBox1.Text += step + "\r\n";
    }
4

1 回答 1

0

不幸的是,这种行为并不意外。进度更新是排队的,并且可以在工作完成后到达。另一方面,任务完成是同步的(假设兼容的上下文)。

在这种情况下,由于您使用的是IProgress<T>,因此您JustDoItAsync永远不需要直接访问 UI。因此,您应该能够以该方法ConfigureAwait(false)在您await的 s 上使用它,并且应该照顾它。

或者,您可以保留一个“标志”,在任务完成时设置它,并在您的进度报告中检查它,但这会使代码相当尴尬:

public async void button1_Click(object sender, EventArgs e)
{
  Action<int> progressUpdate = ProgressUpdate;
  await JustDoItAsync(new Progress<int>(update => progressUpdate?.Invoke(update)));
  progressUpdate = null;
  textBox1.Text += "\r\nDone!\r\n";
}

另一种选择是将标志嵌入到您的IProgress<T>实现中。

于 2017-02-08T14:50:13.097 回答