请注意以下简单代码:
class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
try
{
Task.WhenAny(RunAsync()).GetAwaiter().GetResult();
}
catch (TimeoutException)
{
Console.WriteLine("Timed out");
}
Console.WriteLine("Elapsed: " + sw.Elapsed);
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
private static async Task RunAsync()
{
await Observable.StartAsync(async ct =>
{
for (int i = 0; i < 10; ++i)
{
await Task.Delay(500, ct);
Console.WriteLine("Inside " + i);
}
return Unit.Default;
}).Timeout(TimeSpan.FromMilliseconds(1000));
}
}
运行它输出:
Inside 0
Inside 1
Elapsed: 00:00:01.1723818
Press Enter to exit
注意,没有时间到信息。
现在,如果我更换Task.WhenAny
with Task.WhenAll
这是我得到的:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1362188
Press Enter to exit
请注意时间到这次留言。
而且,如果我删除Task.WhenAll
包装并调用RunAsync
直接地:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1267617
Press Enter to exit
The 时间到正如预期的那样,消息就在那里。
那么到底是怎么回事呢Task.WhenAny
?明明中断了异步方法,但是哪里来的TimeoutException
?
Task.WhenAny
不会重新抛出单个任务的异常(与Task.WhenAll
):
“当任何提供的任务完成时,返回的任务将完成。返回的任务将始终以RanToCompletion
状态及其Result
设置为第一个要完成的任务。即使第一个要完成的任务以Canceled
or Faulted
state."
From Task.WhenAny https://msdn.microsoft.com/en-us/library/hh160383(v=vs.110).aspx
这意味着无论如何它都会成功完成,不会出现任何类型的异常。
要真正重新抛出单个已完成任务的异常,您需要await
返回的任务本身:
var completedTask = await Task.WhenAny(tasks); // no exception
await completedTask; // possible exception
或者在你的情况下:
Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)