OdeToCode IC Logo

Task.CompletedTask and Task.Result Tips

Thursday, January 18, 2018

In any method returning a Task, it is desirable to avoid using Task.Run if you can compute a result without going async. For example, if logic allows you to short-circuit a computation, or if you have a fake method in a test returning a pre-computed answer, then you don't need to use Task.Run.


Here is a method that is not going to do any work, but needs to return a task to fulfill an interface contract for a test:

public Task ComputationWithSideEffects(string someId)
    return Task.Run(() => {
        // i'm just here to simulate hard work

Instead of returning the result of Task.Run, there are two helpers on the Task class that make the code more readable and require a bit less runtime overhead.

For the above scenario, I'd rather use Task.CompletedTask:

public Task ComputationWithSideEffects(string someId)
    return Task.CompletedTask;

What if the caller expects to receive a result from the task? In other words, what if you return a Task<T>? In this scenario, if you already have an answer, use Task.FromResult to wrap the answer.

public Task<Patience> FindPatience()
    if(cachedPatience != null) 
        return Task.FromResult(cachedPatience);
        return ImAlreadyGone();

Gravatar Bjorn Coltof Thursday, January 18, 2018
In the last example the method needs to be async
Gravatar halex2005 Thursday, January 18, 2018
Actually, you don't need to await asynchronous IAmAlreadyGone() method: - your calling method is not marked with "async" keyword - it should already returns Task(Patience)
Gravatar Scott Thursday, January 18, 2018
Thank you. That's what I get for editing code in a word processor.
Gravatar CodeNotFound Tuesday, January 23, 2018
What do you think about ValueTask introduced in C# 7 ? https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-2.0
Gravatar scott Tuesday, January 23, 2018
ValueTask is a great way to avoid allocations.
Comments are closed.