locked
How can async/await not require multithreading?

    Question

  • It is stressed that the async/await feature does not imply multithreading automatically.

    However, the method

    bool GetAWaiter.BeginAwait(Action continuation)  

    returns true when the awaited expression needs to run async and returns false when the awaited expression can be executed sequentially.
    It must return this bool immediately. This implies that the async work needs to happen just before returning this bool because the caller takes back control.
    Does this also not imply that a new thread has to be involved?

    If GetAWaiter.BeginAwait returns true that means async work has to happen. Now let's suppose the awaited async method waits for network IO.
    If everything happens on 1 thread than how can the process know that the wait for the network IO is over and that the continuation can be executed??

    Is the key to understanding this that is a scheduler at work that interleaves processor time *on the same thread* to the main routine and the coroutine(s)?
    Is there another explanation?

    I think my mean question boils down to
    - How is it possible to do everything on 1 thread when multiple "logical" threads of execution needs attention/processor team to make progress.
    - Will the majority of the use cases involve multiple threads ? Or will 1 thread be actually common?

    Kind Regards, Tom Pester
    Tuesday, November 02, 2010 7:53 AM

Answers

  • Hi Tom,

    In the case of overlapped network IO, an IO completion port will be used, the callback being triggered by a hardware interupt.

    This means that while we "await" completion, a thread will not be consumed.

    Once completed, the callback could be scheduled in different ways. For example; all network IO in Silverlight must be performed on the dispatcher/"browser" thread.

    It is possible to do everything on 1 thread.

    It will however depend on the platform, the "awaiter" implementation & the synchronization context being used.

    I'd say the normal use case is that, for the majority of the request, there will only be one thread. An IO completion port thread might be in play while the call back is made into the managed process and marshalled onto the correct syncrhonization context.

    I hope that makes sense. Maybe one of the MS experts can shed some light.


    James Miles http://enumeratethis.com
    Tuesday, November 02, 2010 9:30 AM

All replies

  • Hi Tom,

    In the case of overlapped network IO, an IO completion port will be used, the callback being triggered by a hardware interupt.

    This means that while we "await" completion, a thread will not be consumed.

    Once completed, the callback could be scheduled in different ways. For example; all network IO in Silverlight must be performed on the dispatcher/"browser" thread.

    It is possible to do everything on 1 thread.

    It will however depend on the platform, the "awaiter" implementation & the synchronization context being used.

    I'd say the normal use case is that, for the majority of the request, there will only be one thread. An IO completion port thread might be in play while the call back is made into the managed process and marshalled onto the correct syncrhonization context.

    I hope that makes sense. Maybe one of the MS experts can shed some light.


    James Miles http://enumeratethis.com
    Tuesday, November 02, 2010 9:30 AM


  • I think my mean question boils down to
    - How is it possible to do everything on 1 thread when multiple "logical" threads of execution needs attention/processor team to make progress.
    - Will the majority of the use cases involve multiple threads ? Or will 1 thread be actually common?

    Kind Regards, Tom Pester

    James really answered this thoroughly - but I thought I'd chime in too, but wording it slightly differently.

     

    When you "await" on an expression, you're calling await on a Task.  The Task just represents something that may occur in the future - nothing more.  Because of this, there are at least three separate scenarios:

     

    1) The Task may actually be complete, right now.  In this case, await will just continue without returning to the caller, and no extra thread is used.

    2) The Task will be IO based or using something similar, which will cause it to run using IO ports and not threads.  In this case, no thread is required, as IO ports will signal in hardware without requiring a thread.  I actually think this will be one of the more common cases, as much of the asynchronous code in the framework today uses this method instead of threading.

    3) The Task may be computational in nature, and use one or more additional threads.  This will cause the task to use one or more threads.  This may also become more common, especially as people get to understand and use async/await.  For example, many "tasks" done today via a BackgroundWorker become much easier using async/await - and those are often ones where an additional thread is wanted.

     

    I think the reason that everyone is stressing that tasks != new threads is that the first instinct is to think that using "await" will cause you to be using another thread - this may be true in some cases, but not always.  The idea is more to break that mention association (or prevent it from occurring), not to say that awaiting tasks never use threads.

     

     

     

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Tuesday, November 02, 2010 3:20 PM
  • Thank you both for answering my question.
    Tuesday, November 02, 2010 3:56 PM