142

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?

2
  • 6
    Note, the answers to this question also work just fine for creating a plain Task (no <T>) because Task<T> inherits from Task. Commented Nov 7, 2012 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
    Commented Oct 28, 2018 at 8:28

6 Answers 6

229

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

5
  • 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
    Commented Oct 11, 2012 at 8: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. Commented Dec 18, 2013 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
    Commented Jan 30, 2014 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
    Commented Jan 15, 2015 at 21:25
  • 1
    Task.FromException is not available in .NET 4.5... I think it should be specified.
    – STiLeTT
    Commented Mar 1, 2017 at 10:34
116
private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var taskSource = new TaskCompletionSource<Result>();
    taskSource.SetResult(theResult);
    return taskSource.Task;
}
2
  • 1
    @DanielLobo you might get an answer if you explain what your objection is Commented Jul 23, 2019 at 19:47
  • 2
    Shouldn't it be the one below that is simpler and with a lot more up votes? @user2023861 Commented Jul 23, 2019 at 22:34
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.

1
  • 1
    given the question specifically refers to Task<T> this would be best as a comment
    – Mr. Boy
    Commented Jan 4, 2023 at 13:10
2

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

1

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

Task task = Task.WhenAll();
1
  • 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 Commented Oct 13, 2019 at 19:01
1

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.