Async WCF call to save thread? - c#

In another SO question, I was advised to send an asynchronous network request, rather than sending a synchronous request on a background thread. The reason was so that I don't waste a thread. I'm trying to understand how this is so.
This is the original approach. I can understand how there are two threads here. One is the main thread (1), and one is the background thread (Task.Run) (2) that makes the WCF call:
This is my sketch of the suggested approach. I'm trying to understand how a thread is saved. After the async WCF call, won't another thread be created for the callback from the async WCF call?
After thinking about this further, perhaps only one thread is used if callback processing isn't necessary?

In your WPF client you likely have a OnClick somewhere in your client, where is the thread that is checking if the client was clicked or not?
The answer to that the OS itself is checking for the click then passing the message along to to the message pump which in turn invokes your function. The callback for the WCF function is like that, the OS itself is listening for the reply message and when it gets one it will send a signal that will find a free thread on the thread pool and execute the callback at that time.
The major difference between synchronously holding the thread and letting the callback method generate a thread at the end is the fact that the thread pool is a pool. When a thread in the thread pool finishes its work it does not get destroyed, it waits around a while to see if more work is available to be done and it will be reused to do that new work.
So the two choices are
Have 1 Thread sit there waiting doing no other work waiting for the function to unblock (Sync + thread)
Reuse an existing thread that has finished it's work already (or spawn a new one if none are waiting and we are below ThreadPool.GetMaxThreads()) when the OS tells us the information we where waiting for has shown up, give it the short task of handling the callback, then letting the thread go back in to the pool to do other work for other callbacks as they come in.

Related

System.Threading.Thread - perform operation on it

Ok so lets say all I have is the reference of a System.Threading.Thread called thread A and I'm on another thread, lets say thread B. Now I need to execute a bit of code on thread A for a moment, then switch back. Using the reference I have, how can I Invoke thread A to do an action in it?
Well I'm making a c++/cli library. One of my objects has a thread affinity. I enter a method, I need to swap threads like you would in a Dispatcher.Invoke.
void AllegroSharp::Display::DrawToBackBuffer(BitmapImage^ image)
{
al_draw_bitmap(image->GetBitmap(), (float)image->Rect->Position->X, (float)image->Rect->Position->Y, 0);
}
DrawToBackBuffer gets called on thread B and al_draw_bitmap needs to be called on Thread A, which I have a reference to. How can I do this on thread A? Thread B is just some thread that c# spawned when I did a Task.Run in managed code.
Threads run one set of instructions from start to finish. If thread A is already running, it will execute whatever code it's been told to run from start to finish. You won't be able to change what it's running unless it is actively monitoring some shared memory for instructions on what to do next. Typically the way you implement this is by having a thread run in a loop and, inside that loop, check a message queue. Then have other threads add messages to that queue to give the looping thread work to do. There are a lot more details to make it work right, but that's the basic idea.
If, in your particular scenario, thread A is the application's GUI thread, this message passing mechanism is already set up for you, and you can use Control.Invoke (winforms) or Dispatcher.Invoke (WPF) to pass a unit of work to the GUI thread and wait for it to be completed.
Edit: this answer has been rendered less applicable by the addition of new information to the question. Ah well.

Threads, Task, async/await, Threadpool

I am getting really confused here about multithreading :(
I am reading about the C# Async/Await keywords. I often read, that by using this async feature, the code gets executed "non-blocking". People put code examples in two categories "IO-Bound" and "CPU-bound" - and that I should not use a thread when I execute io-bound things, because that thread will just wait ..
I dont get it... If I do not want a user have to wait for an operation, I have to execute that operation on another thread, right ?
If I use the Threadpool, an instance of "Thread"-class, delegate.BeginInvoke or the TPL -- every asynchronous execution is done on another thread. (with or without a callback)
What you are missing is that not every asynchronous operation is done on another thread. Waiting on an IO operation or a web service call does not require the creation of a thread. On Windows this is done by using the OS I/O Completion Ports.
What happens when you call something like Stream.ReadAsync is that the OS will issue a read command to the disk and then return to the caller. Once the disk completes the read the notifies the OS kernel which will then trigger a call back to your processes. So there is no need to create a new threadpool thread that will just sit and block.
What is meant is this:
Suppose you query some data from a database (on another server) - you will send a request and just wait for the answer. Instead of having a thread block and wait for the return it's better to register an callback that get's called when the data comes back - this is (more or less) what async/await does.
It will free the thread to do other things (give it back to the pool) but once your data come back asynchronously it will get another thread and continue your code at the point you left (it's really some kind of state-machine that handles that).
If your calculation is really CPU intensive (let's say you are calculating prime-numbers) things are different - you are not waiting for some external IO, you are doing heavy work on the CPU - here it's a better idea to use a thread so that your UI will not block.
I dont get it... If I do not want a user have to wait for an operation, I have to execute that operation on another thread, right ?
Not exactly. An operation will take however long it is going to take. When you have a single-user application, running long-running things on a separate thread lets the user interface remain responsive. At the very least this allows the UI to have something like a "Cancel" button that can take user input and cancel processing on the other thread. For some single-user applications, it makes sense to allow the user to keep doing other things while a long-running task completes (for example let them work on one file while another file is uploading or downloading).
For web applications, you do not want to block a thread from the thread pool during lengthy(ish) IO, for example while reading from a database or calling another web service. This is because there are only a limited number of threads available in the thread pool, and if they are all in use, the web server will not be able to accept additional HTTP requests.

When does the CLR create the IO thread when I call BeginXXX()

Suppose I call HttpWebRequest.BeginGetRequestStream() method.
I know that this method is asynchronous and when it's finished, an callback method should be called.
What I'm very sure is that when call the callback method, an I/O thread is created by CLR and this I/O thread do the callback.
What I'm not sure is when I call HttpWebRequest.BeginGetRequestStream(), is there any I/O thread created by CLR? Or just a worker thread created to send the request to the device?
Async IO is thread-less. There is no thread being created or blocked. That is the entire point of using async IO! What would it help you to unblock one thread and block another?
The internals of this have been discussed many times. Basically, the OS notifies the CLR when the IO is done. This causes the CLR to queue the completion callback you specified onto the thread-pool.
Short answer: You don't care.
Long answer:
There is no thread. More exactly, there is no thread for each of the asynchronous request you create. Instead, there's a bunch of I/O threads on the thread pool, which are mostly "waiting" on IOCP - waiting for the kernel to wake them up when data is available.
The important point is that each of these can respond to any notification, they're not (necessarily) selective. If you need to process 1000 responses, you can still do so with just the one thread - and it is only at this point that a thread from the thread pool is requested; it has to execute the callback method. For example, using synchronous methods, you'd have to keep a thousand threads to handle a thousand TCP connections.
Using asynchronous methods, you only need the one IOCP thread, and you only have to spawn (or rather, borrow) new threads to execute the callbacks - which are only being executed after you get new data / connection / whatever, and are returned back to the thread pool as soon as you're done. In practice, this means that a TCP server can handle thousands of simultaneous TCP connections with just a handful of threads. After all, there's little point in spawning more threads than your CPU can handle (which these days is usually around twice as much as you've got cores), and all the things that don't require CPU (like asynchronous I/O) don't require you to spawn new threads. If the handful of processing threads isn't enough, adding more will not help, unlike in the synchronous I/O scenario.

Control.Invoke() stucks

I know there are several threads concerning this topic, but I think mine is different.
In my application I open a form where the user can input some parameters for a upcomming printing. This printing is supposed to be run in a background worker. So I fire that background worker with the event "OnFormClosing".
Within that background worker I need to access the GUI and change/read it, so I need a control.Invoke(). "Sometimes" the Invoke keeps stuck at the invoke call itself and doesn't execute the delegate. My main thread is working fine and is not blocked. I still can interact with the GUI doing other stuff. Before posting any code: Are there any other conditions for executing a control.Invoke() other than
The main GUI thread is not blocked
The contorl must exist, the handle created and not be disposed
The main thread doesn't need to be free and exactly the invoke is called correct? It should continue once the main thread is idle...
Thanks for any help
Update:
Here is the thread situation during that issue:
The Main thread is executing this:
Application.Run(appContext);
So it is idle.
The worker thread is waiting at this line:
fileName = (string)cbPrintFile.Invoke(new Func<String>(() => cbPrintFile.Text));
which is not executed like I state above. cbPrintFile is a combobox
Invoke is "enqueue and wait for it to be processed". If it is becoming "stuck", that suggests that you have deadlocked, for example because the UI thread is still in an event-handler waiting on the worker. If the code is properly de-coupled, you can probably replace the Invoke with BeginInvoke, which allows the worker to continue after queuing the work. Of course, it would also be good to ensure that the UI is never waiting on a worker. This can be done accidentally if trying to hold a lock (on the same object) in both places. You can investigate simply by pausing the application, pressing ctrl+d,t to bring up the threads, and ctrl+d,c to see the call-stack of each in turn.

Does an asynchronous call require an extra thread in the current process or use another thread in a thread pool?

I'm referring to this answer where it says it's not required, there are few specific assumptions though. That question is general.
I'm using C#
Asynchronous process is doing nothing but just calling an external API and waiting for the reply.
Generally yes, but there is at least one exception I can think of. To initiate an asynchronous operation you must transfer the operation outside of the context of the caller. What I mean by that is that the caller should not block waiting for the operation to complete. That usually means that the operation has to move to a newly created thread, a thread from the ThreadPool, an IO completion port, another process, or the like.
I said there was one exception that came to mind. If we slightly pervert our definition of asynchronous we can allow for scenarios in which the initiator does not block waiting for the operation to complete without actually moving the operation to another thread. The best example of this is the UI message pump. In .NET it is easy enough to call Control.BeginInvoke from the UI thread itself to post the execution of a delegate on the same thread. The initiator clearly would not block waiting for the delegate to complete and yet the delegate would eventually start executing on the same thread. This is definitely a perversion of what we typically think of the term asychronous because in this scenario the operation blocks until the caller completes instead of the other way around.
Your question is too general. The Windows API has specific support for asynchronous I/O without using a thread, check the docs for ReadFile() for example. The lpOverlapped argument controls this. The ReadFileEx() function allows specifying an I/O completion callback. This is well covered by the .NET framework classes.
Calling a slow external API function is not covered by this mechanism, you need to spin up your own thread.
Yes, a Pool Thread is used. But that thread is not hanging around waiting for the external device. The thread is re-used and a(nother) thread is called upon when the I/O is completed.
See I/O Asynchronous Completion on MSDN.

Categories

Resources