XperiAndri
XperiAndri

Reputation: 1208

What is the best way to return completed Task?

What is the best way to return a completed Task object?

It is possible to write Task.Delay(0), or Task.FromResult<bool>(true) whatever.

But what is the most efficient way?

Upvotes: 4

Views: 4196

Answers (4)

Flimtix
Flimtix

Reputation: 398

I think that I am a little late. However, I still want to share this answer, for an updated version.

If you want to return a completed task, you should use the following:

return Task.CompletedTask;

This will also automatically set the status to RanToCompletion.

Upvotes: 5

tmaj
tmaj

Reputation: 34947

Here's a little demo which shows the difference in exception handling between methods marked and not marked with async.

public Task<string> GetToken1WithoutAsync() => throw new Exception("Ex1!");

// Warning: This async method lacks 'await' operators and will run synchronously. Consider ...
public async Task<string> GetToken2WithAsync() => throw new Exception("Ex2!");  

public string GetToken3Throws() => throw new Exception("Ex3!");
public async Task<string> GetToken3WithAsync() => await Task.Run(GetToken3Throws);

public async Task<string> GetToken4WithAsync() { throw new Exception("Ex4!"); return await Task.FromResult("X");} 


public static async Task Main(string[] args)
{
    var p = new Program();

    try { var task1 = p.GetToken1WithoutAsync(); } 
    catch( Exception ) { Console.WriteLine("Throws before await.");};

    var task2 = p.GetToken2WithAsync(); // Does not throw;
    try { var token2 = await task2; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};

    var task3 = p.GetToken3WithAsync(); // Does not throw;
    try { var token3 = await task3; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};

    var task4 = p.GetToken4WithAsync(); // Does not throw;
    try { var token4 = await task4; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};
}
// .NETCoreApp,Version=v3.0
Throws before await.
Throws on await.
Throws on await.
Throws on await.

Moved (and edited) from When async Task<T> required by interface, how to get return variable without compiler warning)

Upvotes: 3

Marc Gravell
Marc Gravell

Reputation: 1062494

Task.FromResult would be the most direct. It also includes inbuilt results for a few common integers etc. However, if your value is not an "obvious" value (and won't have inbuilt handling) but is likely to be returned often in your scenario - then you can create your own cached result in a field (maybe static if appropriate) - but it is important to cache the Task, not the result itself.l - otherwise just use Task.FromResult each time.

Upvotes: 4

XperiAndri
XperiAndri

Reputation: 1208

Answer from Stephen Toub (MSFT):

If you want a new Task object each time, Task.FromResult is the most efficient. Task.Delay(0) in its current implementation will return a cached task, but that's an implementation detail. If you want to use a cached task, you should cache one yourself, e.g. private static readonly Task s_completedTask = Task.FromResult(true); and then use s_completedTask.

Upvotes: 5

Related Questions