7
votes

This is more of a general question regarding the asynchronous patterns in C# .NET described on MSDN here.

When a long running synchronous operation is required to be called (eg - WCF, DB query, IO, etc), and I don't want the thread to block (eg - GUI thread), does this mean that there must exist another thread somewhere that does the blocking?

Does making a synchronous call asynchronous necessarily require a thread somewhere to block?

So, if I make 10 long-running async calls (which are actually 10 synchronous calls), must there be 10 threads out there doing the waiting? Or is there a mechanism to prevent 10 threads from being blocked?

In WCF, you can create Begin and End methods for a WCF call to make it asynchronous. Does this mean that when I call this asynchronous method, there is a thread somewhere, either on the client or the server, that does the waiting for me?

I have read several articles about varying methods to achieve asynchrony, but these articles don't explain what is done under the hood.

Update

I made my question more specifc, since I'm more about interested in the .NET. async patterns described by MSDN.

Update 2

I reformed the question to be even more specific to making synchronous calls asynchronous.

5

5 Answers

7
votes

In .NET Framework, there are many ways to implement an asynchronous operation: by using thread, thread pool, BeginXxx and EndXxx methods, event based APM, or Task based APM.

Each async pattern has its own internal implementation and all these Asynchronous Programming Models are explained at this blog article, including the traditional BeginXxx and EndXxx async pattern.

Below is the Summary of all the Async Patterns for quick reference: Async Summary:

Moreover, Jeffrey Richter also explains the CLR Asynchronous Programming Model in MSDN Magazine nicely.

3
votes

It's not necessarily one thread per operation. As @Ioannis Karadimas, says, this most likely depends on the implementation.

For example, imagine I want to do async receives from 10 different sockets. This can be accomplished with a single extra thread using a call to select in a loop, which non-deterministically selects one available socket when a message is received.

2
votes

Unfortunately, there is no single answer to this. Some libraries provide natively implemented asynchronous operations, like sockets for instance, in which it's supported by the hardware. Others might not, like a third - party library that might very well block.

2
votes

'So, if I make 10 long-running async calls, must there be 10 threads out there doing the waiting?' In general, no.

'Or is there a mechanism to prevent 10 threads from being blocked?' - there are mechanisms to allow 1 blocking thread to process multiple items. Simple example - a kernel thread might wait on a NIC signal and an input queue semaphore - it's normally blocked waiting for one or the other. Your async user app queues up a network send and the kernel thread gets it from the queue and tries to submit it to the network card hardware. If it cannot, it adds it to an internal send queue and returns to your app with a 'WOULD_BLOCK' reply. When the hardware is ready, it signals the kernel thread, which dequeues your send buffer and loads it onto the hardware. Similarly, your app sends in one, or more, recv() async requests, (with buffers), and the kernel thread adds it to a list and returns with a 'WOULD_BLOCK' reply. When data comes in to the NIC, its driver signals and the kernel thread inspects the data and tries to find an entry in its list that is waiting for that data. If it is data for your app, it copies/DMAs the data from the hardware into your buffers and calls your async callback, (note, how exactly your asycn callback gets called, and on what thread, is OS-dependent. Maybee an APC is queued up to your GUI thread, or an IOCP completion struct is queued up to a user thread pool).

Anyway, the point is that the kernel thread can have many entries from many processes in its internal send list or recv item list. Whenever the hardware, or its input queue, require attention, it runs and handles it, otherwise it remains blocked.

1
votes

No there will be no Thread WAITING if you make an Async call using the Framework libraries. for eg. As in your use case you have mentioned "In WCF, you can create Begin and End methods for a WCF call to make it asynchronous. Does this mean that when I call this asynchronous method, there is a thread somewhere, either on the client or the server, that does the waiting for me?"

There wont be any thread waiting for the Async operation to be completed, for more details you can check this excellent blog http://blog.stephencleary.com/2013/11/there-is-no-thread.html