c#


What happens to a thread when it 'awaits' something


When an async method awaits a Task what happens to the thread it's currently running on?
I surmise that on a UI thread the message loop resumes and on a thread pool thread the thread is released back to the thread pool. But what happens if the thread was started manually? Are there any other types of threads?
This took me a long time to realize but this part of async-await is dead simple, just go up the call stack. Any time a method awaits something (assuming it's not a completed Task or anything similar) it returns to the caller. Since we're talking about the point where your code cedes control of the thread that means this is the last piece of your code on top of the stack.
If we're running on the UI thread we return back to the message loop. If we're on thread pool thread control returns to the thread pool. A manually created thread only runs a void method, you can only use await if it's an async void method which means it will end the thread at the first await even before the method has completed.
The continuations work the same way. It will queue it on either the UI thread or the thread pool, then it either awaits again or it finishes, ceding control once more.
Edit: I've done some experimenting with custom task schedulers and you can apply the exact same logic there. When the task awaits it cedes control. The task scheduler I used is based off this single threaded task scheduler. In this case ceding control means the task scheduler starts working on the next task in the queue. It's also important to note that the continuations are scheduled with the current task scheduler unless ConfigureAwait(false) is used.
Please note that there is no such thing as a manual thread. They are all just threads. Like electrons, there are not two types of electrons:).
The difference between ThreadPool thread, your thread, UI thread, COM thread etc is if the thread has a message loop, synchronization context.
If the thread has synchronization context, then everything we start on it does not run directly, but it is all started as delegates from some queue and when there is nothing in the queue, the thread is waiting.
So if some part of your code in async method is running on such thread with synchronization context, then on await it stores the context, unless ConfigureAwait and is done with this method and is waiting for next delegate or message for execution. So when the await is done and ConfigureAwait was not used to move next code to thread pool, then it sends to synchronization context new delegate, which is code after await an it gets processed.
Actually, any thread can run async method synchronously and it will wait until
=>
Stephen Cleary pointed out, that this part is not correct: "wait until the async method is done". The wording is really badly misleading. So perhaps this will be little better.
=>
all synchronously executed parts are done. Could be awaiting completed Task, like Task.FromResult. Also, it could be another async method, that could be executed completely synchronously.
But in a moment that await somewhere awaits operation that could not be completed before awaiter is provided, then the t.RunSynchronously will exit even when async method did not run to completion yet.
void ThreadWorker(object obj)
{
var t = new Task<Task>(AsyncMethod);
t.RunSynchronously();
//in this case, it runs the AsyncMethod completely
//and effectively waits for result
}
async Task AsyncMethod()
{
await Something().ConfigureAwait(false);
//everything from here runs on the ThreadPool
}

Related Links

Guid and int identity columns, with code first migrations in MVC, SQL Server, ordering
C# InsertCommand Queries
Can you use Protractor in combination with PageFactory?
Avoid entity framework replacing your property
I have binary serialization/json in c# , how can i achive this in sqlserver
HOGDetector/DetectMultiScale throws IndexOutOfRangeException
Rand a value different than
Convert DataTable to JSON
Unable to Build the C# code through command line
Binding a List<Class> to a ListBox
List of all boot sectors in MSCONFIG boot tab
JSON.NET deserializes an object implementing IDictionary<TKey, TValue> as dictionary, how to force regular class serialization?
Sharepoint Camlex Caml Join error
Parallell unit testing in C# when using TCP listeners?
Instantiate prefab inside canvas
C# Storing class instances in an array to use in other forms

Categories

HOME
azure-documentdb
stata
itunesconnect
ide
system-calls
network-programming
qemu
cluster-analysis
formatting
windows-server-2008
ebay-api
sdk
symfony-3.2
python-3.4
install
browserstack
vsixmanifest
sahi
dcos
adroitlogic
chef-recipe
watson-dialog
aggregate
popup
greensock
ringcentral
vivado-hls
jquery-easyui
views
summernote
android-navigation-drawer
ppp
oracle10g
akavache
marionette
folder
schedule
lines
visual-studio-debugging
availability
android-scrollview
jsonapi-resources
n1ql
matrix-multiplication
blueimp
icu
compiler-warnings
vpython
f#-fake
weld
spring-ide
react.rb
import.io
ionic2-select
ios-keyboard-extension
msiexec
consolidation
eclipse-mars
jira-agile
clique
encode
github-for-mac
android-facebook
updating
persian
uinavigationitem
azure-mobile-app
eula
targetprocess
jeet-grid
crtdbg.h
launcher
parsefloat
nsmutableurlrequest
ios-enterprise
new-operator
boofcv
xml-validation
sygic
static-class
dnsbl
freeimage
shapado
aspmenu-control
motorola-droid
scsf
virtual-printer
log-shipping
overlays
functional-specifications
http-response-codes
table-valued-parameters
mysql-logic
dojox.gfx
user-preferences
cons

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile