0

I'm new to async function, just want to ask why we need TaskAwaiter, when it is just a wrapper of Task, below is some source code

public struct TaskAwaiter<TResult> : ICriticalNotifyCompletion, INotifyCompletion {
   private readonly Task<TResult> m_task;

   internal TaskAwaiter(Task<TResult> task) {
       m_task = task;
   }
   public bool IsCompleted { 
      get { return m_task.IsCompleted; }
   }
   public TResult GetResult();
   public void OnCompleted(Action continuation);
   //...
}

We know that when we await a task such as await task;, the compiler calls the task object's GetAwaiter method, then the a couple of complicated things kicks in, such as state machine, AsyncTaskMethodBuilder etc. But every operation on TaskAwaiter is actually an operation on m_task, so why not just use Task to replace TaskAwaiter?

Theodor Zoulias
  • 24,585
  • 5
  • 40
  • 69
sydevloper
  • 586
  • 8
  • 2
    So that you can write [other types of awaiters](https://stackoverflow.com/a/21702041/11683) to await other [awaitable things](https://stackoverflow.com/a/40868740/11683)? – GSerg Aug 06 '21 at 06:48
  • I would guess that, since the TaskAwaiter is an internal constructor. It could only be constructed by other classes in the same assembly. It can be set once. Also it implements a few interfaces, which the Task probably not implments. It's a kind of inheritance/adding functionality. – Jeroen van Langen Aug 06 '21 at 06:48
  • 2
    We (the developers) do not actually need the `TaskAwaiter`, in the sense that we don't interact with it. The [docs](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.taskawaiter-1) state it clearly: *"This API supports the product infrastructure and is not intended to be used directly from your code."* Are you asking why *they* (the Microsoft software engineers) decided to add this abstraction in the underlying async-await machinery? – Theodor Zoulias Aug 06 '21 at 07:07
  • 1
    There are couple of other [built-in](https://github.com/microsoft/referencesource/tree/master/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices) `Awaiter`s as well. For example the `YieldAwaiter` ([1](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs)) has nothing to do with `Task`. So, we can't always use the underlying Task, because there are cases when there is no such thing. – Peter Csala Aug 09 '21 at 07:38

0 Answers0