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…
。