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();
}
}
Comments
-
Robin over 3 years
What is the best way to handle a
null
task inside anasync
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 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 over 5 yearsNow 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 likevar 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 over 4 years"Task.CompletedTask" is an option, too