Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How asynchronous methods work in C#?

I am using asynchronous methods in some of my project and I like it since it allows my application to be a lot more scalable. However, I am wondering how asynchronous methods really work in background? How .NET (or Windows?) knows that a call is completed? Depending on the number of asynchronous calls I made, I can see that new threads are created (not always though…). Why?

In addition, I would like to monitor how long a request take to complete. To test the concept, I wrote the following code which calls asynchronously a Web service and immediately after starts a stopwatch.

for (int i = 0; i < 10000; i++)
{
    myWebService.BeginMyMethod(new MyRequest(), result, new AsyncCallback(callback), i);
    stopWatches[i].Start();
}
// Call back stop the stopwatch after calling EndMyMethod

This doesn’t work since all the requests (10000) have the same begin time and the duration will go up linearly (call 0 = duration 1, call 1 = duration 2, etc.). How could I monitor the real duration of a call with asynchronous method (from the moment the request is really executed until the end)?


UPDATE: Does an asynchronous method block the flow? I understand that it uses the .NET ThreadPool but how an IAsyncResult know that a call is completed and it's time to call the CallBack method?

like image 225
Martin Avatar asked Oct 24 '09 00:10

Martin


2 Answers

The code is the railroad and the thread is the train. As train goes on railroad it executes the code.

BeginMyMethod is executed by the main thread. If you look inside the BeginMyMethod it simply adds a delegate of MyMethod to the ThreadPool's queue. The actual MyMethod is executed by one of the trains of the train pool. The completion routine that is called when MyMethod is done is executed by the same thread that executed the MyMethod, not by your main thread that runs the rest of the code. While a thread pool thread is busy executing MyMethod, the main thread can either ride some other portion of the railroad system (execute some other code), or simply sleep, waiting until certain semaphore is lit up.

Therefore there's no such thing as IAsyncResult "knowing" when to call the completion routine, instead, completion routine is simply a delegate called by the thread pool's thread right after it's done executing MyMethod.

I hope you don't mind the somewhat childish train analogy, I know it helped me more than once when explaining multithreading to people.

like image 170
Stop Putin Stop War Avatar answered Sep 28 '22 16:09

Stop Putin Stop War


The crux of it is that calling Begin queues up a request to execute your method. The method is actually executed on the ThreadPool, which is a set of worker threads provided by the runtime.

The threadpool is a fixed set of threads to crunch through async tasks as they get put into the queue. That explains why you see the execution time take longer and longer - your methods may each execute in approximately the same time, but they don't start until all previous methods in the queue have been executed.

To monitor the length of time it takes to actually execute the async method, you have to start and stop the timer at the beginning and end of your method.

Here's the docs for the ThreadPool class, and an article about async methods that do a better job of explaining what's going on.

like image 45
Nader Shirazie Avatar answered Sep 28 '22 16:09

Nader Shirazie