为什么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
,这就是我得到的:
Now, if I replace Task.WhenAny
with Task.WhenAll
here is what I get:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1362188
Press Enter to exit
请注意,这次有超时消息出现.
Note the presence of the Timed out message this time.
而且,如果我完全删除了Task.WhenAll
包装器并直接调用RunAsync
:
And, if I remove the Task.WhenAll
wrapper at all and call RunAsync
directly:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1267617
Press Enter to exit
超时消息如预期的那样.
那么Task.WhenAny
有什么用呢?它显然会中断异步方法,但是TimeoutException
在哪里?
So what is the deal with Task.WhenAny
? It obviously interrupts the asynchronous method, but where is the TimeoutException
?
推荐答案
Task.WhenAny
不会从单个任务中抛出异常(与Task.WhenAll
不同):
Task.WhenAny
doesn't rethrow exceptions from the individual tasks (unlike Task.WhenAll
):
返回的任务将在提供的任何任务完成时完成.返回的任务将始终以
Result
状态结束,并且其Result
设置为要完成的第一个任务.即使第一个任务也是如此.要完成的任务以Canceled
或Faulted
状态结束."
"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
这意味着它将成功完成,无论发生什么情况都不会发生任何类型的异常.
That means that it will complete successfully no matter what without any type of exceptions.
要真正抛出单个已完成任务的例外,您需要await
返回的任务本身:
To actually rethrow the exception of the individual completed task you need to await
the returned task itself:
var completedTask = await Task.WhenAny(tasks); // no exception
await completedTask; // possible exception
或者您的情况:
Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();
这篇关于为什么Task.WhenAny没有引发预期的TimeoutException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!