What happens when awaiting on already-completed task?

Though the OP didn't mention ValueTask, I'm adding this answer to include ValueTask since it has been added after this question was originally asked.

  • With regard to Task and Task<T>, as others have noted, you can await a Task (or completed Task) multiple times. If the task has run to completion, it returns immediately.
  • However, if you are using a ValueTask or ValueTask<T>, you cannot await it more than once. ValueTask and ValueTask<T> were introduced in .NET Core 2.0 and are used to avoid/minimize memory allocations for performance-sensitive areas.

As taken from Stephen Toub on the Dotnet Blog:

However, because ValueTask and ValueTask may wrap reusable objects, there are actually significant constraints on their consumption when compared with Task and Task, should someone veer off the desired path of just awaiting them. In general, the following operations should never be performed on a ValueTask / ValueTask:

  • Awaiting a ValueTask / ValueTask multiple times. The underlying object may have been recycled already and be in use by another operation. In contrast, a Task / Task will never transition from a complete to incomplete state, so you can await it as many times as you need to, and will always get the same answer every time.
  • Awaiting a ValueTask / ValueTask concurrently. The underlying object expects to work with only a single callback from a single consumer at a time, and attempting to await it concurrently could easily introduce race conditions and subtle program errors. It’s also just a more specific case of the above bad operation: “awaiting a ValueTask / ValueTask multiple times.” In contrast, Task / Task do support any number of concurrent awaits.
  • Using .GetAwaiter().GetResult() when the operation hasn’t yet completed. The IValueTaskSource / IValueTaskSource implementation need not support blocking until the operation completes, and likely doesn’t, so such an operation is inherently a race condition and is unlikely to behave the way the caller intends. In contrast, Task / Task do enable this, blocking the caller until the task completes.

If you have a ValueTask or a ValueTask and you need to do one of these things, you should use .AsTask() to get a Task / Task and then operate on that resulting task object. After that point, you should never interact with that ValueTask / ValueTask again.

The short rule is this: with a ValueTask or a ValueTask, you should either await it directly (optionally with .ConfigureAwait(false)) or call AsTask() on it directly, and then never use it again, e.g.

and from the MSDN documentation on ValueTask and ValueTask<T>:

The following operations should never be performed on a ValueTask instance:

  • Awaiting the instance multiple times.
  • Calling AsTask multiple times.
  • Using .Result or .GetAwaiter().GetResult() when the operation hasn't yet completed, or using them multiple times.
  • Using more than one of these techniques to consume the instance.

If you do any of the above, the results are undefined.

You can read more about ValueTask and ValueTask<T> here and here.


You will have immédiat the result. Once the task is complete, its result property will contain the result and keep it.


The method that handles the user's request awaits that Task, would it get the value immediately?

Yes. You can think of it as being lazy, if you await a task that is already completed it returns immediately. You could await it several times on different threads and it would only return once it has the result (or is faulted).

Task.CompletedTask was added as a nicety for this very reason. You could await this and it would immediately return a successful task as it has already been completed.


You can create a completed task using Task.FromResult(value) and await it:

var result = await Task.FromResult(5);
Debug.Assert(result == 5);

This is useful for example if you have a method which can return cached data but needs to fetch it asynchronously the first time.

So, yes, you can await already completed tasks.