请注意以下简单代码:
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
替换为 Task.WhenAll
,这就是我得到的:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1362188
Press Enter to exit
请注意这次出现了Timed out 消息。
而且,如果我完全删除 Task.WhenAll
包装器并直接调用 RunAsync
:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1267617
Press Enter to exit
正如预期的那样,超时 消息出现了。
那么 Task.WhenAny
是怎么回事?明明打断了异步方法,可是TimeoutException
在哪里呢?
最佳答案
Task.WhenAny
不会从单个任务中重新抛出异常(与 Task.WhenAll
不同):
"The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the
RanToCompletion
state with itsResult
set to the first task to complete. This is true even if the first task to complete ended in theCanceled
orFaulted
state."
来自 Task.WhenAny
这意味着无论如何它都会成功完成,没有任何类型的异常。
要真正重新抛出单个已完成任务的异常,您需要await
返回的任务本身:
var completedTask = await Task.WhenAny(tasks); // no exception
await completedTask; // possible exception
或者在你的情况下:
Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();
关于c# - 为什么 Task.WhenAny 没有抛出预期的 TimeoutException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31544684/