Coder Perfect

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

Problem

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

        #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();
        }
    }
}

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 https://stackoverflow.com/questions/13127177/if-my-interface-must-return-task-what-is-the-best-way-to-have-a-no-operation-imp