如果我的界面必须返回任务是什么有没有操作实现的最佳途径?(If my interface must

2019-06-18 17:28发布

在下面的代码,由于接口,类LazyBar必须从它的方法(和为了讨论不能改变)返回的任务。 如果LazyBar的实现是不寻常的,因为它发生在快速同步运行-什么是从方法返回一个空操作任务的最佳方法是什么?

我已经与Task.Delay(0)以下,但是我想知道这是否有任何性能的副作用,如果函数被调用了很多 (为了讨论各种情形,说上百次),:

  • 这是否语法糖未风大的东西?
  • 是否开始堵塞我的应用程序的线程池?
  • 是编译器菜刀足以应对Delay(0)不同?
  • return Task.Run(() => { }); 有什么不同?

有没有更好的办法?

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

Answer 1:

使用Task.FromResult(0)Task.FromResult<object>(null)将产生较少的开销比创建Task与无操作的表达。 当创建Task与结果预先确定,没有调度开销参与。


今天,我会建议使用Task.CompletedTask做到这一点。



Answer 2:

要添加到里德·科普塞的回答有关使用Task.FromResult ,可以提高性能,即使你的缓存已经完成的任务,因为完成任务的所有实例都一样多:

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

随着TaskExtensions.CompletedTask您可以使用相同的实例在整个应用程序域。


在.Net框架(V4.6)的最新版本增加了这一点与Task.CompletedTask静态属性

Task completedTask = Task.CompletedTask;


Answer 3:

Task.Delay(0)作为接受的答案是一个很好的方法,因为它是一个完整的缓存副本Task

截至目前4.6有Task.CompletedTask这是它的目的更加明确,但不仅Task.Delay(0)仍然会返回一个缓存实例,它返回一样的一个缓存实例Task.CompletedTask

既不的缓存本质是保证保持不变,但由于执行相关的优化是唯一的实现依赖作为优化技术(也就是,他们还是会正常工作,如果实现改变的东西,仍然是有效的)使用的Task.Delay(0)比接受的答案更好。



Answer 4:

最近遇到了这一点,并一直得到有关该方法的无效警告/错误。

我们是在安抚编译器的业务,这清除它:

    public async Task MyVoidAsyncMethod()
    {
        await Task.CompletedTask;
    }

这这里汇集了所有最好的建议至今。 没有return语句是必要的,除非你实际做的方法的东西。



Answer 5:

我喜欢Task completedTask = Task.CompletedTask; 净4.6的溶液,但另一种方法是标记方法异步并返回void:

    public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
    {
    }

你会得到一个警告(CS1998 - 异步功能,无需等待表达式),但是这是安全在这方面,不容忽视。



文章来源: If my interface must return Task what is the best way to have a no-operation implementation?