为什么Task.WhenAny没有引发预期的TimeoutException? [英] Why does the Task.WhenAny not throw an expected TimeoutException?

查看:168
本文介绍了为什么Task.WhenAny没有引发预期的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设置为要完成的第一个任务.即使第一个任务也是如此.要完成的任务以CanceledFaulted状态结束."

"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

这意味着它将成功完成,无论发生什么情况都不会发生任何类型的异常.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆