Task<> 对象上的 C# async/await Progress 事件

标签 c# async-await

我对 C# 5 的新 async 完全陌生/await关键字,我对实现进度事件的最佳方式很感兴趣。

现在我更喜欢 Progress事件发生在 Task<>本身。我知道我可以将事件放在包含异步方法的类中并在事件处理程序中传递某种状态对象,但对我来说这更像是一种变通方法而不是解决方案。我可能还希望不同的任务触发不同对象中的事件处理程序,这样听起来很困惑。

有什么办法可以做类似下面的事情吗?:

var task = scanner.PerformScanAsync();
task.ProgressUpdate += scanner_ProgressUpdate;
return await task;

最佳答案

推荐的方法在 Task-based Asynchronous Pattern 中有描述。文档,它为每个异步方法提供了自己的 IProgress<T> :

public async Task PerformScanAsync(IProgress<MyScanProgress> progress)
{
  ...
  if (progress != null)
    progress.Report(new MyScanProgress(...));
}

用法:

var progress = new Progress<MyScanProgress>();
progress.ProgressChanged += ...
PerformScanAsync(progress);

注意事项:

  1. 按照惯例,progress参数可能是 null如果来电者不需要进度报告,那么请务必在您的 async 中检查这一点方法。
  2. 进度报告本身是异步的,因此您应该在每次调用时创建一个新的参数实例(更好的是,只需为您的事件参数使用不可变类型)。您应该改变并重新使用相同的参数对象多次调用 Progress .
  3. Progress<T> type 将在构造时捕获当前上下文(例如,UI 上下文)并将提高其 ProgressChanged在这种情况下发生的事件。因此,您不必担心在调用 Report 之前编码(marshal)回 UI 线程。 .

关于Task<> 对象上的 C# async/await Progress 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15408148/

相关文章:

c# - String.ToLowerInvariant() 如何确定它必须转换成什么字符串/字符?

c# - 单元测试 webapi 异步操作

c# - 多个异步/等待链接

c# - Task.StartNew() 在 STA 模式下的工作方式不同?

c# - 使用 DotNetOpenAuth 保护的 WCF 4 Soap 和 Json 端点

c# - ComboBox items.count 与数据源不匹配

c# - View 模型应该包含静态功能方法吗?

c# - 冷任务和 TaskExtensions.Unwrap

c# - 异步不会在单元测试中的同一线程上继续

c# - : this(foo) syntax in C# constructors?