Coder Perfect

What is the best method to implement a no-operation implementation if my interface must return Task?


The class LazyBar in the code below must return a task from its method due to the interface (and can’t be modified for the sake of argument). What is the best way to return a No-Operation task from the method if the LazyBars implementation is special in that it runs swiftly and synchronously?

I chose Task.Delay(0) below, but I’m curious whether there are any performance implications if the function is called frequently (for example, hundreds of times per second):

Is there a better way to do things?

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);


    internal class Program
        private static void Main(string[] args)

        private static async void Test()
            IFooFace foo = FactoryCreate();
            await foo.WillBeLongRunningAsyncInTheMajorityOfImplementations();

        private static IFooFace FactoryCreate()
            return new LazyBar();

Asked by Jon Rea

Solution #1

Today, I would advise you to use Task. This task has been completed.

Pre .net 4.6:

Using the Task Task or FromResult(0). When compared to generating a Task with a no-op expression, FromResultobject>(null) has less overhead. There is no scheduling overhead when creating a Task with a pre-determined result.

Answered by Reed Copsey

Solution #2

I’d like to add to Reed Copsey’s response concerning Task. Because all instances of finished jobs are the same, you can increase efficiency even further by caching the already completed task:

public static class TaskExtensions
    public static readonly Task CompletedTask = Task.FromResult(false);

You can utilize the same instance of TaskExtensions.CompletedTask across the whole app domain with TaskExtensions.CompletedTask.

The Task in the newest version of the.Net Framework (v4.6) does just that. completedTask is a static property that is set to true after a task is completed.

Task completedTask = Task.CompletedTask;

Answered by i3arnon

Solution #3

Task. Because it is a cached duplicate of a completed Task, Delay(0), as in the acceptable response, was a good approach.

Task is now available in version 4.6. Not only does Task, but also CompletedTask, which is more obvious in its goal. Delay(0) still return a single cached instance, it returns the same single cached instance as does Task. CompletedTask.

The use of Task is just implementation-dependent as optimizations (i.e., it would still operate correctly if the implementation changed to something still valid). The approved answer was better than Delay(0).

Answered by Jon Hanna

Solution #4

I came across this recently and started receiving warnings/errors about the function being void.

We’re here to appease the compiler, and this clarifies things:

    public async Task MyVoidAsyncMethod()
        await Task.CompletedTask;

This combines the best of all of the previous suggestions. Unless you’re actually performing something in the method, there’s no need for a return statement.

Answered by Alexander Trauzzi

Solution #5

return Task.CompletedTask; // this will make the compiler happy

Answered by Xin

Post is based on