如果我的界面必须返回任务什么是最好的方式有一个无操作的实现?

在下面的代码中,由于接口, 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(); } } } 

使用Task.FromResult(0)Task.FromResult<object>(null)将比使用no-opexpression式创buildTask开销less。 当创build预定义结果的Task时,不涉及调度开销。


今天,我会build议使用Task.CompletedTask来完成这一点。

要添加到Reed Copsey有关使用Task.FromResult 的答案中 ,如果caching已完成的任务,则可以进一步提高性能,因为所有已完成任务的实例都是相同的:

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

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


.Net Framework(v4.6)的最新版本增加了Task.CompletedTask静态属性

 Task completedTask = Task.CompletedTask; 

Task.Delay(0)与在答案中一样是一个好方法,因为它是已完成Task的caching副本。

从4.6开始,现在Task.CompletedTask更明确的Task.CompletedTask ,但是Task.Delay(0)不仅返回单个caching实例,而且返回 Task.CompletedTask 相同的单个caching实例。

两者的caching本质都保证保持不变,但是作为依赖于实现的优化只作为优化的实现依赖优化(也就是说,如果实现更改为仍然有效的,它们仍然可以正常工作)使用Task.Delay(0)比接受的答案好。

我更喜欢Task completedTask = Task.CompletedTask; .net 4.6的解决scheme,但另一种方法是将方法标记为async并返回void:

  public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations() { } 

你会得到一个警告(CS1998 – asynchronous函数没有等待expression式),但在这种情况下,这是安全的忽略。

最近遇到这个,不断有关于该方法的警告/错误是无效的。

我们正在安抚编译器,清除它:

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

这汇总了迄今为止所有build议中最好的一个。 除非您真的在方法中做某件事,否则不需要返回语句。