为什么 Task.WhenAny 没有抛出预期的 TimeoutException?
Why does the Task.WhenAny not throw an expected TimeoutException?
请注意以下简单代码:
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 its Result
set to the first task to complete. This is true even if the first task to complete ended in the Canceled
or Faulted
state."
这意味着它无论如何都会成功完成,没有任何类型的异常。
要真正重新抛出单个已完成任务的异常,您需要 await
返回的任务本身:
var completedTask = await Task.WhenAny(tasks); // no exception
await completedTask; // possible exception
或者您的情况:
Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();
请注意以下简单代码:
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."
这意味着它无论如何都会成功完成,没有任何类型的异常。
要真正重新抛出单个已完成任务的异常,您需要 await
返回的任务本身:
var completedTask = await Task.WhenAny(tasks); // no exception
await completedTask; // possible exception
或者您的情况:
Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();