C# 异步等待从内部任务结果获取异常

C# 异步等待从内部任务结果获取异常,c#,async-await,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.

给出以下代码段:

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,状态=RanToCompletion,方法=“{null}”,结果=“System.Threading.Tasks.unapprovisie``1[System.Threading.Tasks.TaskExtensions+VoidResult]”的属性。

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

r.Exception==null

r.Result
不可访问

更新

var r = Task.WhenAny(tasks).Result; // produces exactly the same wrapped result!
在调试器中,它如下所示:


您的问题在于任务的执行方式。
什么时候起作用<代码>任务。WhenAny
返回其结果为已完成任务的任务。这就是为什么
read.Result
是一个任务,而这个任务又包含异常

目前还不清楚所需的语义是什么,但如果您希望
StartReading
显示第一个完成任务的结果,可以使用“双重等待”,如下所示:

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

在旁注中,不要使用
StartNew
。如果需要将CPU绑定(或其他阻塞代码)移出UI线程,请使用
Task.Run
;否则,只需直接调用方法。

我发现问题的另一个解决方案是将结果强制转换到
Task

施放
任务的结果。任何时候
也将获得内部任务

 var result = Task.WhenAny(reading, activityCheck).Result;
var inner = ((Task<Task>)result).Result;
inner.Exception...
var result=Task.WhenAny(读取、活动检查).result;
var内部=((任务)结果).result;
内部。例外。。。

不确定这是否相关,但
Task.Factory.StartNew
不支持
async
委托。使用
Task。改为运行
。另外,您创建新任务以调用异步方法(如
CheckActivityTimeout
)的原因是什么?为什么不直接调用它们呢?将代码更改为使用
Task.Run
会得到相同的结果。因此
wait-wait-Task.WhenAny(reading,activityCheck)是投票赞成的答案,嗯?我本以为应该只有一个
await
——就像我的回答所说的那样。@DavidPine:
await-await
观察内部任务异常。也就是说,内部的
await
获取最先完成的任务(该
await
从不失败);然后外部
wait
观察该任务的结果,传播任何异常。感谢分享!今天我学到了一些东西。。。“不过有点难看。”戴维平:是的,这是一个托苏。您也可以执行
wait Task.WhenAny(…).Unwrap()一些人更喜欢的。无论哪种方式,这都是一个罕见的用例。既然您可以链接
。展开
,那么您是否也可以链接
wait wait…