c# - 为什么 Task.WhenAny 没有抛出预期的 TimeoutException?

标签 c# .net async-await task-parallel-library system.reactive

请注意以下简单代码:

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."

来自 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/

相关文章:

c# - 为什么我不能使用以下 IEnumerable<string>?

c# - 我需要有关 "this"关键字和继承的帮助

c# - 为什么在 machine.config 中定义了 TransactionScope 超时?

c# - 在 .Net 中创建和验证 x509 证书

c# - 对线程池输出进行排序以流式传输数据

c# - 如何在 for 循环中使用日期时间?

c# - 从 TimerCallback 函数更新 UI 线程 Windows Phone 8

c# - 异步等待以保持事件触发

javascript - 在 puppeteer/JavaScript 中重试 page.goto、page.waitForNavigation 等的最佳实践

node.js - MQTTjs 库的无序输出