2010-11-22 155 views
100

我正在实施一种方法Task<Result> StartSomeTask(),并且在调用该方法之前碰巧知道了结果。如何创建已完成的Task<T>创建完成的任务<T>

这是目前我在做什么:

private readonly Result theResult = new Result(); 

public override Task<Result> StartSomeTask() 
{ 
    var task = new Task<Result>(() => theResult); 
    task.RunSynchronously(CurrentThreadTaskScheduler.CurrentThread); 
    return task; 
} 

有没有更好的解决办法?

+6

注意,这个问题的答案也工作得很好创建一个普通的任务(无),因为任务从任务继承。 – 2012-11-07 19:56:17

回答

102
private readonly Result theResult = new Result(); 

public override Task<Result> StartSomeTask() 
{ 
    var taskSource = new TaskCompletionSource<Result>(); 
    taskSource.SetResult(theResult); 
    return taskSource.Task; 
} 
162

当目标.NET 4.5,你可以使用Task.FromResult

public static Task<TResult> FromResult<TResult>(TResult result); 

要创建一个失败的任务,使用Task.FromException

public static Task FromException(Exception exception); 
public static Task<TResult> FromException<TResult>(Exception exception); 

.NET 4.6增加了Task.CompletedTask,如果你需要一个非通用Task

public static Task CompletedTask { get; } 

变通办法较旧版本的.NET的:

  • 当异步靶向包(或AsyncCTP)针对.NET 4.0中,您可以使用TaskEx.FromResult代替。

  • 要获得非通用Task .NET 4.6之前,你可以使用Task<T>Task派生并调用​​或Task.FromResult(0)的事实。

+13

要返回非通用任务,最好使用类似Task.FromResult(0)的东西。使用“null”作为参数会混淆不能确定通用参数的编译器。 – Whyllee 2012-10-11 08:30:25

+0

异常情况如何?异步方法被编译到状态机中,捕获异常并将它们保存在返回的任务中。甚至在首次等待之前执行的代码也会发生。返回Task.FromResult的方法可能会直接抛出异常。 – 2013-12-18 18:51:01

+0

@RobertVažan一个有趣的边缘案例。可以说,如果你从一个方法中检索你已知的result_,并且该方法抛出异常,那么就有一个需要修复的缺陷。 – Gusdor 2014-01-30 16:10:28

1

如果您使用的是Rx,则替代方法是Observable.Return(result).ToTask()。

12

对于没有返回值的任务,.NET 4.6已添加Task.CompletedTask

它返回一个已经在TaskStatus.RanToCompletion中的任务。它可能每次都返回相同的实例,但文档警告您不要指望这一事实。

0

调用Task.WhenAll没有任何参数将返回一个完成的任务。

Task task = Task.WhenAll();