K4E
K4E

Reputation: 21

Where is the best place to check a Task.WhenAll() for a null result in C#?

I am picking up looking at someone's code & need some advice over the use of Task.WhenAll().

We have the following simplified code:

Task<List<class1>> t1 = Task<List<class1>>.Factory.StartNew(LoadClass1);
Task<List<class2>> t2 = Task<List<class2>>.Factory.StartNew(LoadClass2);
Task<List<class3>> t3 = Task<List<class3>>.Factory.StartNew(LoadClass3);

var tasks = new Task[] { t1, t2, t3 };

The methods LoadClass1/2/3 are API calls to a service to get some data.

Task loadAllDataTask = Task.WhenAll(tasks);
try
{
    await loadAllDataTask;
    _class1Result = t1.Result;
    _class2Result = t2.Result;
    _class3Result = t3.Result;
}
catch (Exception)
{
    if (loadAllDataTask.Exception != null)
    {
        throw loadAllDataTask.Exception;
    }
}

The issue I am trying to resolve is when the API service is down. The tasks are awaited, and say one of the tasks endpoints t3 is down, it returns a 500 error. The task does not fail but returns a null value.

There is then a NullReference exception fall over in the method LoadClass3 as it's just assigning the .Result of the API call and returning it out.

Now in this example it's small but I have about 15 tasks that get going. Is there a way I can handle the exception of a null value for any task result within the Task.WhenAll? Can I simply do something like for each task:

_class1Result = t1.Result ?? throw new Exception();

Wrap this round all the tasks?

Cheers for any advice

Upvotes: 1

Views: 720

Answers (1)

maxc137
maxc137

Reputation: 2761

If result of the Task is null, and task is not failed - this is valid result. There is nothing wrong with this. If for you null is not an expected result, you can add checks for that inside function with task or even wrap task. Or even wrap your task inside another task that will perform the check.

Something like this:

Task<List<class1>> t1 = Task<List<class1>>.Factory.StartNew(NullCheck(LoadClass1));

...

async Task<T> NullCheck<T>(Task<T> task)
{
    T taskResult = await task;
    _ = taskResult ?? throw new InvalidOperationException("Result cannot be null");

    return taskResult;
}

Upvotes: 1

Related Questions