Confusion regarding threads and if asynchronous methods are truly asynchronous in C#

This is a little unclear to me probably because the definition of asynchronous in my head is not lining up.

Good on you for asking for clarification.

In my mind, since I do mainly UI dev, async code is code that does not run on the UI thread, but on some other thread.

That belief is common but false. There is no requirement that asynchronous code run on any second thread.

Imagine that you are cooking breakfast. You put some toast in the toaster, and while you are waiting for the toast to pop, you go through your mail from yesterday, pay some bills, and hey, the toast popped up. You finish paying that bill and then go butter your toast.

Where in there did you hire a second worker to watch your toaster?

You didn’t. Threads are workers. Asynchronous workflows can happen all on one thread. The point of the asynchronous workflow is to avoid hiring more workers if you can possibly avoid it.

If I have a long running task that is CPU bound (let’s say it is doing a lot of hard math), then running that task asynchronously must be blocking some thread right? Something has to actually do the math.

Here, I’ll give you a hard problem to solve. Here’s a column of 100 numbers; please add them up by hand. So you add the first to the second and make a total. Then you add the running total to the third and get a total. Then, oh, hell, the second page of numbers is missing. Remember where you were, and go make some toast. Oh, while the toast was toasting, a letter arrived with the remaining numbers. When you’re done buttering the toast, go keep on adding up those numbers, and remember to eat the toast the next time you have a free moment.

Where is the part where you hired another worker to add the numbers? Computationally expensive work need not be synchronous, and need not block a thread. The thing that makes computational work potentially asynchronous is the ability to stop it, remember where you were, go do something else, remember what to do after that, and resume where you left off.

Now it is certainly possible to hire a second worker who does nothing but add numbers, and then is fired. And you could ask that worker “are you done?” and if the answer is no, you could go make a sandwich until they are done. That way both you and the worker are busy. But there is not a requirement that asynchrony involve multiple workers.

If I await it then some thread is getting blocked.

NO NO NO. This is the most important part of your misunderstanding. await does not mean “go start this job asynchronously”. await means “I have an asynchronously produced result here that might not be available. If it is not available, find some other work to do on this thread so that we are not blocking the thread. Await is the opposite of what you just said.

What is an example of a truly asynchronous method and how would they actually work? Are those limited to I/O operations which take advantage of some hardware capabilities so no thread is ever blocked?

Asynchronous work often involves custom hardware or multiple threads, but it need not.

Don’t think about workers. Think about workflows. The essence of asynchrony is breaking up workflows into little parts such that you can determine the order in which those parts must happen, and then executing each part in turn, but allowing parts that do not have dependencies with each other to be interleaved.

In an asynchronous workflow you can easily detect places in the workflow where a dependency between parts is expressed. Such parts are marked with await. That’s the meaning of await: the code which follows depends upon this portion of the workflow being completed, so if it is not completed, go find some other task to do, and come back here later when the task is completed. The whole point is to keep the worker working, even in a world where needed results are being produced in the future.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)