给定以下代码段:
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!
在调试器中它看起来像这样:
最佳答案
您的问题是因为 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/