4

I am little bit confuse for WaitAll and WaitAny. I am trying to get exception but when i do WaitAll it return exception but When use WaitAny returns nothing.And necessary is that if any of task complete work done.Is their any Replacement of WaitAny(). WaitAll and WhenAll are different becuase i dont want let all task done. Like

try
{
    int i = 0;
    Task t1 = Task.Factory.StartNew(() =>
        {
            i = 2 * 4;
        });

    Task<int> t2 = Task.Factory.StartNew(() =>
        {
            int a = 0;
            int b = 100 / a;
            return 0;
        });

    Task[] tasks = new Task[] { t1, t2 };
    Task.WaitAny(tasks);
    //Task.WaitAll(tasks);// Working

}
catch (AggregateException ae)
{
    var message = ae.InnerException.Message;
    Console.WriteLine(message);
}
Console.ReadLine();
shaair
  • 945
  • 12
  • 24
  • 7
    What's the confusion - you said you wanted to wait for *any* of the tasks to complete. It's highly likely (but not guaranteed) that `t1` will complete successfully before `t2` raises an exception, so you're told that `t1` completed successfully and you can carry on merrily with your normal flow. – Damien_The_Unbeliever Mar 16 '17 at 11:59
  • Same question here: http://stackoverflow.com/q/29681272/613130 – xanatos Mar 16 '17 at 12:01
  • I'd suggest using TAP and `Task.WhenAll` and `Task.WhenAny`, they are more modern and just "work better." https://msdn.microsoft.com/en-us/library/hh873175(v=vs.110).aspx – Jodrell Mar 16 '17 at 12:06
  • Situation like i have to use WaitAny so how got exception? Because I need if any one of task completed then boom work done. – shaair Mar 16 '17 at 12:09
  • 1
    @Damien_The_Unbeliever that's not competely true, because even if both tasks will throw an exception - WaitAny will not throw. So WaitAny does not tell you that task compelted _successfully_, just that it completed (and perfectly possible that this means it failed). – Evk Mar 16 '17 at 12:24
  • Base example, easy to modify here: https://ideone.com/EebAcT, that shows that `Task.WaitAny` will stop waiting after an exception, but won't rethrow the exception. – xanatos Mar 16 '17 at 12:27
  • You may find this interesting: [How can I await an array of tasks and stop waiting on first exception?](https://stackoverflow.com/questions/57313252/how-can-i-await-an-array-of-tasks-and-stop-waiting-on-first-exception) – Theodor Zoulias May 05 '20 at 04:35

3 Answers3

4

This is called Unobserved Exception, which basically means that exception in newly created threads in Task Parallel Library (TPL) ThreadPool, is not caught by the other thread or as stated in aforementioned link:

While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default. Rather, the exception will end up getting eaten after the event is raised, regardless of whether an event handler observes the exception.

This means that when using WaitAny(), if one of the tasks completes without any exception, exceptions in other tasks will not be caught.

S.Dav
  • 2,436
  • 16
  • 22
  • I'll add that the `WaitAny()` will still "return" if one thread throws exception and the others are still "working". – xanatos Mar 16 '17 at 12:18
3

Maybe you want something like this. Note, this uses the Task-based Asynchronous Pattern.

public static Task<Task[]> WhenAllOrFirstException(params Task[] tasks)
{
    var countdownEvent = new CountdownEvent(tasks.Length);
    var completer = new TaskCompletionSource<Task[]>();

    Action<Task> onCompletion = completed =>
        {
            if (completed.IsFaulted && completed.Exception != null)
            {
                completer.TrySetException(completed.Exception.InnerExceptions);
            }

            if(countdownEvent.Signal() && !completer.Task.IsCompleted)
            {
                completer.TrySetResult(tasks);
            }
        };

    foreach(var task in tasks)
    {
        task.ContinueWith(onCompletion)
    }

    return completer.Task;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Jodrell
  • 34,946
  • 5
  • 87
  • 124
0

Your WaitAny implementation will throw error as well it depends what task will complete first. WaitAny does not wait till looser task (in most cases it would be t2) got completed - so it won't got exception from it.

Update

Indeed WaitAny will not return any error as descriobed here Task.WhenAny and Unobserved Exceptions

Community
  • 1
  • 1
klashar
  • 2,519
  • 2
  • 28
  • 38
  • If any case situation like this but i dont need to WaitAll() task to be completed. One Task got exception then how can get exception? Does garbage collection threw? – shaair Mar 16 '17 at 12:06
  • WaitAny won't throw at all, regardless of which task completes first. – Evk Mar 16 '17 at 12:15