创建一个完成的任务

时间:2013-01-09 18:36:49

标签: c# .net async-await task-parallel-library

我想创建一个完整的Task(不是Task<T>)。 .NET中是否有内置的东西可以做到这一点?

相关问题: Create a completed Task<T>

7 个答案:

答案 0 :(得分:213)

newest version of .Net (v4.6)正在添加内置的Task.CompletedTask

Task completedTask = Task.CompletedTask;

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

答案 1 :(得分:142)

Task<T>可以隐式转换为Task,因此只需获得已完成的Task<T>(包含任何T和任何值)并使用它。你可以使用这样的东西来隐藏实际结果存在于某个地方的事实。

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

请注意,由于我们没有公开结果,并且任务总是完成,我们可以缓存单个任务并重复使用它。

如果您使用的是.NET 4.0且没有FromResult,那么您可以使用TaskCompletionSource创建自己的版本:

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

答案 2 :(得分:57)

我这样做的首选方法是在没有参数的情况下调用Task.WhenAll()MSDN documentation表示“如果提供的数组/可枚举不包含任务,则返回的任务将在返回给调用者之前立即转换到RanToCompletion状态。”这听起来像你想要的。

更新:我在Microsoft's Reference Source找到了来源;在那里你可以看到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()来公开的。

答案 3 :(得分:32)

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

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

答案 4 :(得分:26)

您可以使用Task.FromResult(在.NET 4.5中)返回已完成的Task<T>

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

答案 5 :(得分:7)

您可以使用来自Nito.AsyncEx.TaskConstants.Completed的优秀图书馆AsyncEx中的Stephen Cleary

答案 6 :(得分:7)

对于.Net 4.6及以上版本使用

return Task.CompletedTask;

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

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