10

I would like to wait all task, but some of them can be null. It is a code like that:

Task<MyType1> myTask1 = getData01Async();
Task<MyTyp2> myTask2 = null;
Task<MyType3> myTask3 = null;

if(myVariable == true)
{
    myTask2 = getData02Async();
}
else
{
    myTask3 = getData03Async();
}


wait Task.WhenAll(myTask1, myTask2, myTask3);

The idea is, task1 always exists, but task2 and task3 depends of a variable. So I would like to run all the task in parallel and wait when all of them are finished. And if one task is null, the treat it as it is finished.

The problem with this code is that I get a null reference exception when it runs.

There are some way to do that? Or what another alternatives could I use?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Álvaro García
  • 18,114
  • 30
  • 102
  • 193

4 Answers4

17

Just filter the null tasks out:

await Task.WhenAll(new Task[] { task1, task2, task3 }.Where(i => i != null));
armenm
  • 922
  • 6
  • 9
11

Well, depending on your scenario you could assign completed tasks or put them in an array/list and then pass this list to WhenAll:

Task<MyType1> myTask1 = getData01Async();
Task<MyType2> myTask2 = Task.FromResult((MyType2) null);
Task<MyType3> myTask3 = Task.FromResult((MyType3) null);

...

await Task.WhenAll(myTask1, myTask2, myTask3);
Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • 1
    Thanks, This really helped me out. I had multiple tasks with different result types of which I was not sure the tasks should trigger. And with this solution I could still work with the results without worrying about what type the generic Task returned when adding everything to a list! – gogessj4 Jun 12 '19 at 15:51
  • The only non-obvious suggestion. Thanks! – Andriy Volkov Oct 29 '19 at 15:22
  • 1
    This is the best solution. Very easy to just do myTask = x != null ? MyAsync() : Task.CompletedResult instead of creating arrays and filtering on them. – Erndob May 14 '20 at 04:56
7

Use a collection to track the tasks that aren't null. Then pass that list to Task.WhenAll method like below:

var tasks = new List<Task>();

Task<MyType1> myTask1 = getData01Async();
tasks.Add(myTask1);

Task<MyTyp2> myTask2 = null;
Task<MyType3> myTask3 = null;

if(myVariable == true)
{
    myTask2 = getData02Async();
    tasks.Add(myTask2);
}
else
{
    myTask3 = getData03Async();
    tasks.Add(myTask3);
}

await Task.WhenAll(tasks);
CodeNotFound
  • 22,153
  • 10
  • 68
  • 69
3

To build on what @UweKeim suggested, why not simply filter out the null tasks when you pass them to the WhenAll.

public async Task FilterNullTasks()
{
    Task<string> myTask1 = Task.Delay(1000).ContinueWith(tsk => string.Empty);
    Task<int> myTask2 = null;
    Task<bool> myTask3 = null;

    await Task.WhenAll(new Task[]
    {
        myTask1, myTask2, myTask3
    }.Where(tsk => tsk != null));
}
JSteward
  • 6,833
  • 2
  • 21
  • 30