Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Please, observe the following trivial code:

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));
    }
}

Running it outputs:

Inside 0
Inside 1
Elapsed: 00:00:01.1723818
Press Enter to exit

Note, no Timed out message.

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.

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

The Timed out message is there, as expected.

So what is the deal with Task.WhenAny ? It obviously interrupts the asynchronous method, but where is the TimeoutException?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
584 views
Welcome To Ask or Share your Answers For Others

1 Answer

Task.WhenAny doesn't rethrow exceptions from the individual tasks (unlike 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."

From Task.WhenAny

That means that it will complete successfully no matter what without any type of exceptions.

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

Or in your case:

Task.WhenAny(RunAsync()).GetAwaiter().GetResult().GetAwaiter().GetResult();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...