c# - 异步等待从内部任务结果中获取异常

标签 c# async-await

给定以下代码段:

public Task StartReading()
{
  var activityCheck = Task.Factory.StartNew(async () => await this.CheckActivityTimeout(), this._token.Token).Unwrap();
  var reading = Task.Factory.StartNew(async () => await this.ReadAsync(), this._token.Token).Unwrap();

  // for reference, this code produces the same result:
  // var activityCheck = this.CheckActivityTimeout();
  // var reading = this.ReadAsync();

  return Task.WhenAny(reading, activityCheck);
}

当在 CheckActivityTimeout 中抛出异常时,我按如下方式捕获它。

var read = StartReading()
var tasks = new Task[] { read, taskx, tasky, taskz };
int completed = Task.WaitAny(tasks);
var r = tasks[completed];

r 没有设置异常。相反,如果我查看调试器,我会发现任务 r 将异常存储在 Result 属性中。我如何获得这个实际结果?

r 的类型 Id = 17,Status = RanToCompletion,Method = "{null}",Result = "System.Threading.Tasks.UnwrapPromise``1[System.Threading. Tasks.TaskExtensions+VoidResult]"

您可以看到实际异常在内部 任务的结果中。如何向上传播?

r.Exception == null
r.Result 不可访问。

更新

var r = Task.WhenAny(tasks).Result; // produces exactly the same wrapped result!

在调试器中它看起来像这样:

enter image description here

最佳答案

您的问题是因为 Task.WhenAny 的工作方式。 Task.WhenAny 返回一个任务,其结果是完成的任务。这就是为什么 read.Result 是一个任务,它又包含异常。

不太清楚期望的语义是什么,但如果您希望StartReading显示第一个完成任务的结果,您可以使用“双重等待” ,像这样:

public async Task StartReadingAsync()
{
  var activityCheck = this.CheckActivityTimeout();
  var reading = this.ReadAsync();
  await await Task.WhenAny(reading, activityCheck);
}

请注意,不要使用 StartNew。如果您有需要从 UI 线程移出的 CPU 绑定(bind)(或其他阻塞代码),则使用 Task.Run;否则,直接调用方法即可。

关于c# - 异步等待从内部任务结果中获取异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35201174/

相关文章:

javascript - 同步与立即异步执行性能基准

javascript - 如何使链式 firebase 查询异步

c# - ASP.Net MVC 4 Bundles - 在路径名中使用变量

javascript - 如何在 ASP.NET C# 页面加载之前获取动态创建的控件的值

javascript - 嵌套异步/等待函数

c# - 异步等待会丢失 http 上下文吗?

c# - 数据库国际化

c# - WCF REST 服务 - 无法返回对象列表

c# - Linq to Entity 和加载 EntitySet

javascript - 等待内部的等待不会给出正确的输出