给出以下代码段:
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)
在调试器中它看起来像这样:
你的问题是因为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; 否则,只需直接调用方法.
| 归档时间: |
|
| 查看次数: |
238 次 |
| 最近记录: |