141

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?

dtb
  • 213,145
  • 36
  • 401
  • 431
  • 6
    Note, the answers to this question also work just fine for creating a plain Task (no ) because Task inherits from Task. – Tim Lovell-Smith Nov 07 '12 at 19:56
  • Note that today there's `ValueTask` for completed tasks (i.e. for values you already have so that code is essentially synchronous), which will save you an allocation. – nawfal Oct 28 '18 at 08:28

6 Answers6

226

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).

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • 13
    To return a non generic task, it's better to use something like Task.FromResult(0). Using "null" as parameter can confuse compiler which cannot determine the generic parameter. – Whyllee Oct 11 '12 at 08:30
  • What about exceptions? Async methods are compiled into state machine that catches exceptions and saves them in the returned Task. This happens even for code executing before first await. Method returning Task.FromResult might throw exceptions directly. – Robert Važan Dec 18 '13 at 18:51
  • @RobertVažan An interesting edge case. Arguably, if you are retrieving your _known result_ from a method and that method throws exceptions then there is a defect that needs fixing. – Gusdor Jan 30 '14 at 16:10
  • 1
    @RobertVažan You can easily write your own `FromException` method, that behaves like `FromResult` but instead represents a faulted task. Such a method can simply return that for its error cases if it's important for the exception to be represented in the resulting task. – Servy Jan 15 '15 at 21:25
  • 1
    Task.FromException is not available in .NET 4.5... I think it should be specified. – STiLeTT Mar 01 '17 at 10:34
115
private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var taskSource = new TaskCompletionSource<Result>();
    taskSource.SetResult(theResult);
    return taskSource.Task;
}
QrystaL
  • 4,886
  • 2
  • 24
  • 28
11

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

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

Daryl
  • 3,654
  • 1
  • 14
  • 14
2

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

Niall Connaughton
  • 15,518
  • 10
  • 52
  • 48
1

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

Task task = Task.WhenAll();
zumalifeguard
  • 8,648
  • 5
  • 43
  • 56
  • while this will work, it an obscure workaround that might confuse people when reading the code as it implies waiting for tasks that don't exist – Adrian Hristov Oct 13 '19 at 19:01
0

You can try var myAlreadyCompletedTask = Task.FromResult<string>("MyValue") This will give you a task with a specified return type

Atif Rehman
  • 417
  • 6
  • 6