创建已完成的任务

本文关键字:任务 已完成 创建 | 更新日期: 2023-09-27 17:51:05

我想创建一个完整的Task(不是Task<T>(。.NET 中是否内置了一些东西来执行此操作?

一个相关的问题:创建已完成的任务

创建已完成的任务

最新版本的

.Net(v4.6(正在添加内置的Task.CompleteTask:

Task completedTask = Task.CompletedTask;

该属性作为无锁单例实现,因此您几乎总是使用相同的已完成任务。

Task<T>可以隐式转换为Task,所以只需获取一个完整的Task<T>(具有任何T和任何值(并使用它。 您可以使用这样的东西来隐藏实际结果在某处的事实。

private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
    return completedTask;
}

请注意,由于我们不公开结果,并且任务始终完成,因此我们可以缓存单个任务并重用它。

如果您使用的是 .NET 4.0

并且没有FromResult则可以使用 TaskCompletionSource 创建自己的 .NET 4.0:

public static Task<T> FromResult<T>(T value)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(value);
    return tcs.Task;
}

我的首选方法是调用不带参数的Task.WhenAll()。MSDN 文档指出"如果提供的数组/枚举不包含任何任务,则返回的任务将立即转换为 RanToCompletion 状态,然后再返回到调用方。这听起来像你想要的。

更新:我在Microsoft的参考源中找到了源代码;在那里您可以看到Task.WhenAll包含以下内容:

return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
            Task.CompletedTask :
            new WhenAllPromise(tasks);

所以 Task.CompleteTask 确实是内部的,但它是通过调用没有参数的 WhenAll(( 来公开的。

我会使用Task.Delay(0).在内部,它返回已完成Task<T>的缓存实例。这正是当前答案建议做的,只是现在您不必自己缓存实例,也不必在代码中有任何不优雅的垃圾值。

您可能认为您可以使用Task.Yield(),但事实证明Task.Yield()的结果不是Task的子类型,而Task.Delay(0)的结果是。这是两者之间的微妙区别之一。

您可以使用

Task.FromResult(在 .NET 4.5 中(返回已完成的Task<T>

如果您需要非泛型Task,则始终可以使用Task.FromResult(0)或类似名称,因为Task<T>Task的子类。

对于 .Net 4.6 及更高版本

return Task.CompletedTask;

对于较低版本,您可以使用

return new Task(() => { });

您可以使用 Nito.AsyncEx.TaskConstants.Complete,来自 Stephen Cleary 的伟大库 AsyncEx。

怎么样:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

如果您不介意,可以省略警告抑制。