【发布时间】:2015-10-11 05:44:56
【问题描述】:
请注意以下琐碎的代码:
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
Timed out 消息如预期的那样存在。
那么Task.WhenAny 是怎么回事?明明打断了异步方法,但是TimeoutException在哪里呢?
【问题讨论】:
-
你为什么用
.Task.GetAwaiter().GetResult(),首先它等同于Task.Result,其次你很可能会被一个grue吃掉。 -
@Aron 这不是等价的。它抛出了实际的异常。但是,是的,它仍然处于阻塞状态,可能会导致死锁。
-
Task.getAwaiter():
This method is intended for compiler use rather than for use in application code. -
@sstan - 我知道,但它是唯一真正等同于
await的阻塞。.Result或.Wait()具有不同的异常处理语义。
标签: c# .net async-await task-parallel-library system.reactive