提问者:小点点

如果我的接口必须返回Task,那么拥有无操作实现的最佳方式是什么?


在下面的代码中,由于接口的关系,类必须从它的方法返回一个任务(而且为了arguments的缘故,不能更改)。如果

下面我使用了,但是我想知道如果函数被多次调用(为了争论起见,比方说一秒钟调用数百次),这是否会对性能产生副作用:

  • 句法上的sugar dun-wind to sight?/li> ?/li> {)/code>是否不同?/li>

有没有更好的办法?

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

共3个答案

匿名用户

今天,我建议使用Task.CompletedTask来实现这一点。

净价4.6:

使用(null)/code>将比使用no-op表达式创建产生更少的开销。当创建具有预定结果的时,不涉及调度开销。

匿名用户

为了补充ReedCopsey关于使用的回答,如果缓存已经完成的任务,则可以更好地提高性能,因为所有已完成任务的实例都是相同的:

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

使用,您可以在整个应用程序域中使用相同的实例。

NET Framework(V4.6)的最新版本通过静态属性添加了这一点

Task completedTask = Task.CompletedTask;

匿名用户

接受答案中的是一个好方法,因为它是已完成的的缓存副本。

从4.6开始,的用途更加明确,但不仅仍然返回单个缓存实例,而且返回与相同的单个缓存实例。

两者的缓存性质都不能保证保持不变,但是作为仅依赖于实现的优化(也就是说,如果实现更改为仍然有效的内容,它们仍然可以正常工作),使用比接受的答案要好。