请注意下面这段简单的代码:
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
注意这次出现了已超时的消息。
如果完全删除Task.WhenAll
包装并直接调用RunAsync
:
Inside 0
Inside 1
Timed out
Elapsed: 00:00:01.1267617
Press Enter to exit
正如预期的那样,出现了超时消息。
那么Task.WhenAny
是怎么回事呢?它显然会中断异步方法,但是TimeoutException
在哪里呢?
.Task.GetAwaiter().GetResult()
,首先它等同于Task.Result
,其次你很可能会被吃掉。 - Aron此方法旨在供编译器使用,而不是应用程序代码中使用。
- sstanawait
。.Result
或.Wait()
具有不同的异常处理语义。 - mark