.Net最新版本(v4.6)正在增加一个内置的Task.CompletedTask:
Task completedTask = Task.CompletedTask;
该属性实现为无锁单例,因此您几乎总是使用相同的已完成任务。
Task.CompletedTask
仍然是内部的。 - Peter RitchieTask<T>
可以隐式转换为Task
,所以只需获取已完成的Task<T>
(任何T
和任何值)并使用它。您可以像这样使用它来隐藏实际结果的存在。
private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
return completedTask;
}
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
我偏爱的方法是调用不带参数的Task.WhenAll()
。根据MSDN文档:“如果提供的数组/可枚举对象不包含任何任务,则返回的任务将在返回给调用方之前立即转换为已完成状态。” 这听起来就像你想要的。
更新:我在Microsoft参考源中找到了源代码; 在那里,你可以看到Task.WhenAll包含以下内容:
return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
Task.CompletedTask :
new WhenAllPromise(tasks);
因此,Task.CompletedTask确实是内部的,但通过调用WhenAll()而没有参数来公开它。
Task.Delay(0)
。在内部,它返回一个已完成的Task<T>
实例的缓存副本。这正是当前答案建议做的事情,现在你不必自己缓存实例,也不会在代码中有任何不雅观的垃圾值。Task.Yield()
,但是事实证明,Task.Yield()
的结果不是Task
的子类型,而Task.Delay(0)
的结果则是。这是两者之间的微妙差异之一。您可以在.NET 4.5中使用Task.FromResult返回已完成的Task<T>
。
如果您需要一个非泛型的Task
,则始终可以使用Task.FromResult(0)
或类似方法,因为Task<T>
是Task
的子类。
对于 .Net 4.6 及以上版本,请使用
return Task.CompletedTask;
对于低版本,您可以使用
return new Task(() => { });
return Task.Delay(0);
代替怎么样? - Miquel这样怎么样:
#pragma warning disable 1998
public async Task emptyTask() {
}
#pragma warning restore 1998
如果你不介意的话,可以省略警告抑制。
ValueTask
用于已完成的任务(即对于您已经拥有的值,使代码本质上是同步的),这将节省您的分配。 - nawfal