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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With