async await从内部任务结果中获取异常

Jim*_*Jim 4 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);
}
Run Code Online (Sandbox Code Playgroud)

当抛出异常时CheckActivityTimeout,我会按如下方式捕获它.

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

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!
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

Ste*_*ary 6

你的问题是因为Task.WhenAny工作原理.Task.WhenAny返回一个任务,其结果是已完成的任务.这就是为什么read.Result是一个任务,而这个任务又包含异常.

它并不是很清楚所需的语义是什么,但是如果你想要StartReading显示第一个完成任务的结果,你可以使用"double await",如下所示:

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

另外,请不要使用StartNew.如果你需要移出UI线程的CPU绑定(或其他阻塞代码),那么使用Task.Run; 否则,只需直接调用方法.