I was watching a vid about Async CTP and saw that if you call await from e.g. main thread , then the execution will continue from main thread when the work is completed.
e.g
//called from main thread
var result = await SomeAsyncWork();
//this will execute in main thread also
console.writeline(result)
I had the naive impression that there would be a normal call back going on which would be executed on a worker thread.
At some level that must be what is going on since you can wrap normal async methods in a Task of T with Task.FromAsync
but normal async methods will run in worker threads, so how is the callback in the workerthread marshalled back to the main thread?
The callback is attached to the task, using the current task scheduler (that's "current" at the time of awaiting, not current at the time of completion). For a UI thread, the current task scheduler will schedule the callback to be executed within the UI thread... for a thread pool thread, the scheduler will allow it to be executed on any thread pool thread, etc.
Assuming you're awaiting a Task<T>
, it's effectively calling Task<T>.ContinueWith(continuationAction, scheduler)
.
You can await anything with the right methods available, but how BeginAwait
schedules the continuation is implementation-specific. I've only mentioned the task-based one because it's probably the most common one. The compiler itself doesn't specify this at all - it assumes that the libraries will do the right thing. All the compiler does is translate "the rest of the method" into a continuation, and pass that into BeginAwait
.
The compiler compiles your code differently and splits it so that code after await becomes a callback. There's a detailed explanation to a certain extent here:
http://evolpin.wordpress.com/2011/05/02/c-5-await-and-async-in-asp-net/