In the code below, due to the interface, the class LazyBar
must return a task from its method (and for argument's sake can't be changed). If LazyBar
s implementation is unusual in that it happens to run quickly and synchronously - what is the best way to return a No-Operation task from the method?
I have gone with Task.Delay(0)
below, however I would like to know if this has any performance side-effects if the function is called a lot (for argument's sake, say hundreds of times a second):
Does this syntactic sugar un-wind to something big?
Does it start clogging up my application's thread pool?
Is the compiler cleaver enough to deal with Delay(0) differently?
Would return Task.Run(() => { }); be any different?
Is there a better way?
using System.Threading.Tasks;
namespace MyAsyncTest
{
internal interface IFooFace
{
Task WillBeLongRunningAsyncInTheMajorityOfImplementations();
}
/// <summary>
/// An implementation, that unlike most cases, will not have a long-running
/// operation in 'WillBeLongRunningAsyncInTheMajorityOfImplementations'
/// </summary>
internal class LazyBar : IFooFace
{
#region IFooFace Members
public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
{
// First, do something really quick
var x = 1;
// Can't return 'null' here! Does 'Task.Delay(0)' have any performance considerations?
// Is it a real no-op, or if I call this a lot, will it adversely affect the
// underlying thread-pool? Better way?
return Task.Delay(0);
// Any different?
// return Task.Run(() => { });
// If my task returned something, I would do:
// return Task.FromResult<int>(12345);
}
#endregion
}
internal class Program
{
private static void Main(string[] args)
{
Test();
}
private static async void Test()
{
IFooFace foo = FactoryCreate();
await foo.WillBeLongRunningAsyncInTheMajorityOfImplementations();
return;
}
private static IFooFace FactoryCreate()
{
return new LazyBar();
}
}
}
Task.FromResult<object>(null)
.
Today, I would recommend using Task.CompletedTask to accomplish this.
Pre .net 4.6:
Using Task.FromResult(0)
or Task.FromResult<object>(null)
will incur less overhead than creating a Task
with a no-op expression. When creating a Task
with a result pre-determined, there is no scheduling overhead involved.
To add to Reed Copsey's answer about using Task.FromResult
, you can improve performance even more if you cache the already completed task since all instances of completed tasks are the same:
public static class TaskExtensions
{
public static readonly Task CompletedTask = Task.FromResult(false);
}
With TaskExtensions.CompletedTask
you can use the same instance throughout the entire app domain.
The latest version of the .Net Framework (v4.6) adds just that with the Task.CompletedTask
static property
Task completedTask = Task.CompletedTask;
public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
as well as public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
. So, we can either return CompletedTask;
or await CompletedTask;
. What is more preferrable (maybe more efficient or more congruent)?
Task.Delay(0)
as in the accepted answer was a good approach, as it is a cached copy of a completed Task
.
As of 4.6 there's now Task.CompletedTask
which is more explicit in its purpose, but not only does Task.Delay(0)
still return a single cached instance, it returns the same single cached instance as does Task.CompletedTask
.
The cached nature of neither is guaranteed to remain constant, but as implementation-dependent optimisations that are only implementation-dependent as optimisations (that is, they'd still work correctly if the implementation changed to something that was still valid) the use of Task.Delay(0)
was better than the accepted answer.
Task.CompletedTask
can't be used in PCL project, even if I set the .net version to 4.6 (profile 7), just tested in VS2017.
Task.CompletedTask => Task.Delay(0);
to support that, so I don't know for sure off the top of my head.
Recently encountered this and kept getting warnings/errors about the method being void.
We're in the business of placating the compiler and this clears it up:
public async Task MyVoidAsyncMethod()
{
await Task.CompletedTask;
}
This brings together the best of all the advice here so far. No return statement is necessary unless you're actually doing something in the method.
public Task MyVoidAsyncMethod() {}
is completely the same as above method. If there is a usecase for using it like this, please add the additional code.
return Task.CompletedTask; // this will make the compiler happy
return
didn't work for me - for an async
Task, I had to just use await Task.CompletedTask
.
return Task.CompletedTask
should help. However, if your function definition prob return void, then you can await
When you must return specified type:
Task.FromResult<MyClass>(null);
I prefer the Task completedTask = Task.CompletedTask;
solution of .Net 4.6, but another approach is to mark the method async and return void:
public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
{
}
You'll get a warning (CS1998 - Async function without await expression), but this is safe to ignore in this context.
If you are using generics, all answer will give us compile error. You can use return default(T);
. Sample below to explain further.
public async Task<T> GetItemAsync<T>(string id)
{
try
{
var response = await this._container.ReadItemAsync<T>(id, new PartitionKey(id));
return response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return default(T);
}
}
return await Task.FromResult(new MyClass());
Success story sharing
return default(YourReturnType);
Task.CompletedTask
might do the trick! (but requires .net 4.6)