Best way to handle null task inside async method?

26,203

Solution 1

You don't need to handle null tasks. Simply null check it:

public async Task Execute()
{
   if (task != null)
   {
       await task;
   }
}

Or even better, simply return the task since you're not adding anything after the await:

public Task Execute()
{
   return task;
}

If you want to return a completed task instead of null you can use Task.FromResult:

public Task Execute()
{
   return task ?? Task.FromResult(false);
}

Solution 2

Most asynchronous code is cleaner if tasks are never null. Instead of a null task, use Task.FromResult(0) or some such construct.

public class MyClass
{
  private readonly Task task;
  public MyClass(Task task) { this.task = task ?? Task.FromResult(0); }

  public async Task ExecuteAsync()
  {
    await task;
  }
}

Or, if that's really all your ExecuteAsync is doing:

public Task ExecuteAsync()
{
  return task;
}

Note that the task is already running when the constructor is called, which makes the method name ExecuteAsync a misnomer. If you want the task to start when ExecuteAsync is called, then what you really want to store is a Func<Task>:

public class MyClass
{
  private readonly Func<Task> func;
  public MyClass(Func<Task> func) { this.func = func ?? () => Task.FromResult(0); }

  public async Task ExecuteAsync()
  {
    await func();
  }
}
Share:
26,203
Robin
Author by

Robin

SOreadytohelp

Updated on December 19, 2020

Comments

  • Robin
    Robin over 3 years

    What is the best way to handle a null task inside an async method?

    public class MyClass
    {
       private readonly Task task;
       public MyClass(Task task) { this.task = task; }
    
       public async Task Execute()
       {
          if (task == null)
          {
             await Task.Yield(); /* Is this the best way? */
             return;
          }
          await task;
       }
    }
    
  • Xcalibur37
    Xcalibur37 over 8 years
    "Task.FromResult(false)" works great when you have an overridable method that you can't make strictly abstract. Thanks for the excellent answer.
  • BrainSlugs83
    BrainSlugs83 over 5 years
    Now that the Elvis operator is so common (.?) -- I have an extension method that uses this approach to make sure those await calls always work: public static Task<T> NullSafe<T>(this Task<T> task) => task ?? Task.FromResult(default(T)); -- so you can write code like var x = await (someObject?.DoTheThing()).NullSafe(); (Keep in mind, because of the way that the Elvis operator works, the parenthesis are significant in this statement.)
  • Jesse Sierks
    Jesse Sierks over 4 years
    "Task.CompletedTask" is an option, too