Question

I'm implementing a method Task<Result> StartSomeTask() and happen to know the result already before the method is called. How do I create a Task<T> that has already completed?

This is what I'm currently doing:

private readonly Result theResult = new Result();

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

Is there a better solution?

Was it helpful?

Solution

private readonly Result theResult = new Result();

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

OTHER TIPS

When targeting .NET 4.5 you can use Task.FromResult:

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

To create a failed task, use Task.FromException:

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

.NET 4.6 adds Task.CompletedTask if you need a non generic Task.

public static Task CompletedTask { get; }

Workarounds for older versions of .NET:

  • When targeting .NET 4.0 with Async Targetting Pack (or AsyncCTP) you can use TaskEx.FromResult instead.

  • To get non-generic Task prior to .NET 4.6, you can use the fact that Task<T> derives from Task and just call Task.FromResult<object>(null) or Task.FromResult(0).

For tasks with no return value, .NET 4.6 has added Task.CompletedTask.

It returns a task which is already in TaskStatus.RanToCompletion. It probably returns the same instance every time, but the documentation warns you not to count on that fact.

If you're using Rx, an alternative is Observable.Return(result).ToTask().

Calling Task.WhenAll without any parameters will return a completed task.

Task task = Task.WhenAll();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top