Coder Perfect

What’s the difference between asynchronous and multithreading programming?


I assumed they were essentially the same thing: developing programs that divide tasks across processors (on machines with two or more processors). Then I come upon this, which reads:

I’m wondering if someone could translate that for me into English. It appears to make a distinction between asyncronicity (is that a word?) and threading, implying that a software with asynchronous jobs but no multithreading can exist.

Now I grasp the concept of asynchronous tasks, as demonstrated in Jon Skeet’s C# In Depth, Third Edition example on page 467.

async void DisplayWebsiteLength ( object sender, EventArgs e )
    label.Text = "Fetching ...";
    using ( HttpClient client = new HttpClient() )
        Task<string> task = client.GetStringAsync("");
        string text = await task;
        label.Text = text.Length.ToString();

“This function, whenever it is called, will not be invoked in a context where its completion is required for everything after its call to be called,” says the async keyword.

To put it another way, it was written in the middle of a task.

int x = 5; 
double y = Math.Pow((double)x,2000.0);

, because DisplayWebsiteLength() has nothing to do with x or y, will cause DisplayWebsiteLength() to be run “in the background,” as if it were a script.

                processor 1                |      processor 2
int x = 5;                                 |  DisplayWebsiteLength()
double y = Math.Pow((double)x,2000.0);     |

Obviously, that’s a ridiculous scenario, but am I correct or am I completely lost?

(I’m also perplexed as to why the words sender and e are never utilized in the body of the above function.)

Asked by user5648283

Solution #1

This is a very common mistake. Multithreading and asynchrony are sometimes confused, but they are not the same thing.

An analogy is frequently useful. You’re working as a chef in a restaurant. An order for eggs and toast is placed.

Is it now clear that multithreading is just one type of asynchrony? Asynchrony is about tasks, while threading is about workers. Workers are assigned tasks in multithreaded workflows. In asynchronous single-threaded workflows, you have a network of tasks, some of which are dependent on the outcomes of others; as each job completes, the code that schedules the next task that can run based on the results of the just-completed task is invoked. However, you should only require one worker to complete all of the jobs, rather than one worker for each task.

It is beneficial to recognize that many tasks are not processor-dependent. It makes sense to recruit as many workers (threads) as there are processors, give one task to each worker, allocate one processor to each worker, and have each processor do nothing but compute the output as soon as possible for processor-bound jobs. However, you don’t need to allocate a worker to tasks that don’t require a processor. You simply wait for the message that the result is available to arrive and then do anything else while you wait. When you receive that message, you can schedule the completion of the finished activity as the next item on your to-do list.

So let’s take a closer look at Jon’s example. So, what happens next?

It’s the same as in my analogy. Someone requests a document from you. You send the document off in the mail and go about your business. You are notified when it comes in the mail, and you complete the rest of the workflow whenever you feel like it — open the envelope, pay the delivery fees, etc. You don’t need to recruit another employee to take care of everything.

Answered by Eric Lippert

Solution #2

In-browser Javascript is a wonderful example of a single-threaded asynchronous program.

You won’t have to worry about numerous pieces of code handling the same object at the same time because each function will complete before any other javascript on the page is permitted to start.

When making an AJAX request, however, no code is executed, thus other javascript can respond to events like clicks until the request is returned and the callback associated with it is invoked. If any of these other event handlers are still active when the AJAX request is returned, their handler will not be called until they are finished. There’s only one JavaScript “thread” running, even though it’s possible for you to effectively pause the thing you were doing until you have the information you need.

When dealing with UI elements in C# programs, the same issue happens: you’re only permitted to interact with them when you’re on the UI thread. If a user clicks a button, and you want to respond by reading a large file from the disk, an inexperienced programmer might make the mistake of reading the file within the click event handler itself, causing the application to “freeze” until the file finishes loading because it can’t respond to any more clicking, hovering, or other UI-related events until that thread is freed.

To circumvent this problem, programmers might construct a new thread to load the file, then inform that thread’s code that once the file is loaded, it needs to execute the remaining code on the UI thread again so that it can change UI components based on what it found in the file. This technique was popular until recently since it was what the C# libraries and language made simple, but it’s inherently more difficult than it has to be.

If you think about what the CPU is doing when it reads a file at the level of the hardware and Operating System, it’s basically issuing an instruction to read pieces of data from the disk into memory, and to hit the operating system with an “interrupt” when the read is complete. To put it another way, reading from disk (or any other type of I/O) is intrinsically asynchronous. The concept of a thread waiting for that I/O to complete is an abstraction that the library developers created to make it easier to program against. It’s not necessary.

In.NET, most I/O operations now have a corresponding…Async() function, which produces a Task almost instantly. You can add callbacks to this Task to define code to be executed when the asynchronous process is finished. You can also indicate which thread that code should run on, as well as a token that the asynchronous operation can check periodically to see whether you’ve opted to cancel the asynchronous task, allowing it to finish its work efficiently and gracefully.

C# was considerably more explicit about how callback code was invoked before the async/await keywords were created, because callbacks were in the form of delegates that you connected with the job. Async/await abstracts away the establishment of such delegates to provide you the benefit of employing the…Async() method while reducing code complexity. But they’re still there in the compiled code.

So you can have your UI event handler wait for an I/O operation, freeing up the UI thread to perform other things, and then return to it once you’ve completed reading the file—all without ever having to create a new thread.

Answered by StriplingWarrior

Post is based on