如果我的界面必须返回任务什么是最好的方式有一个无操作的实现?
在下面的代码中,由于接口, 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议中最好的一个。 除非您真的在方法中做某件事,否则不需要返回语句。