using delegates in ASP.NET to handle asynchronous operations - c#

When calling BeginInvoke on a delegate, the action is executed on a separate thread. If called in ASP.NET does it use a CLR worker thread? Or does it use an IIS worker thread?
If the latter, then I will need to employ an asynchronous ASP.NET pattern to ensure the action is executed on a CLR worker thread. But I would rather not do that if the action ends up there upon BeginInvoke.

it uses a CLR worker thread.
as described in here
To begin with, ASP.NET uses the process-wide CLR thread pool to service requests (for more background on the CLR thread pool, see the .NET column in this issue).
EDIT:
another resource is this blog
Unfortunately, the thread used by BeginInvoke is actually taken from the same worker thread pool that is used by ASP.Net to handle Page Requests

Thread usage/management is a bit different in IIS6, IIS7 and IIS 7.5.
Pretty detail and updated explanation here:
ASP.NET Thread Usage on IIS 7.5, IIS 7.0, and IIS 6.0
Not sure if this answers your question but a good read anyways.

Using a custom delegate and calling its BeginInvoke method offer a quick way to fire off worker threads for your application. But unfortunately, they hurt the overall performance of your application since they consume threads from the same pool used by ASP.NET to handle HTTP requests.
Just remember too, if the callback from the Asynchronous method is important then, you need to block the main thread from returning to the client until the asynchronous process has completed. If the logging and analytics is a 'fire-and-forget' method call, then things are easier and you can just fire off the method and allow the server to respond to the client. However, if the callback is important and the server has completed processing, nothing is happening on the server to handle the callback once completed; this is where asynchronous processing on the server for ASP.NET applications differs from say a WinForms application.

Related

Async/await in Web.API 2 Controllers Action [duplicate]

Background
We are currently developing a web application, which relies on ASP .NET MVC 5, Angular.JS 1.4, Web API 2 and Entity Framework 6. For scalability reasons, the web application heavility relies on the async/await pattern. Our domain requires some cpu-intensive calculations, which can takes some seconds (<10s). In the past some team members used Task.Run, in order to speed up the calculations.Since starting an extra thread inside ASP .NET MVC or Web API controllers is considered a bad practise (the thread is not known by the IIS, so not considered on AppDomain Recycle => See Stephen Cleary's blog post), they used ConfigureAwait(false).
Example
public async Task CalculateAsync(double param1, double param2)
{
// CalculateSync is synchronous and cpu-intensive (<10s)
await Task.Run(() => this.CalculateSync(param1, param2))).ConfigureAwait(false);
}
Questions
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Does ConfigureAwait(false) really avoid the creation of an extra thread?
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Zero. None. In fact, you're hindering performance by spawning a new thread. Within the context of a web application, spawning a thread is not the same thing as running in the "background". This is due to the nature of a web request. When there's an incoming request, a thread is taken from the pool to service the request. Using async allows the thread to be returned before the end of the request, if and only if the thread is in a wait-state, i.e. idle. Spawning a thread to do work on, effectively idles the primary thread, allowing it to be returned to the pool, but you've still got an active thread. Returning the original thread to the pool does nothing at that point. Then, when the new thread finishes its work, you've got to request a main thread back from the pool, and finally return the response. The response cannot be returned until all work has completed, so whether you use 1 thread or a hundred, async or sync, the response cannot be returned until everything finishes. Therefore, using additional threads does nothing but add overhead.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
No, or more appropriately, it's not about that. ConfigureAwait is just an optimization hint, and only determines whether the original context is maintained between thread jumps. Long and short, it has nothing to do with the creation of a thread, and at least in the context of an ASP.NET application, has negligible performance impact either way.
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
No. And it doesn't matter whether it's CPU bound or not.
Task.Run offloads work to a ThreadPool thread. The web api request already uses a ThreadPool thread so you're just limiting scalability by offloading to another thread with no reason.
This is useful in UI apps, where the UI thread is a special single thread.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
It doesn't affect thread creating in one way or another. All it does is configures whether to resume on the captured SynchronizationContext or not.
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Think about what really happens - Task.Run() creates a Task on the thread pool, and your await operator will free the thread (I'm assuming all methods down the stack are also awaiting). Now your thread is back to the pool, and it might pick up that same Task! In this scenario, there is obviously no performance gain. There is performance hit, actually. But if the thread picks up another Task (that's probably what will happen), another thread would have to pick up CalculateSync() Task and continue from where the former stopped. It would have made more sense to let the original thread execute CalculateSync() in the first place, no Tasks involved, and let the other thread have the other queued Tasks.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
Not at all. It merely points out that the continuation shouldn't be executed on the caller's context.
There is one more thing that you need to consider. As you told your your api is doing CPU intensive task then async/await help to run the process in another thread and free your app pool for another request. Means your web api can handle more number of request per second if you use async/await correctly.
In your case look like this.CalculateSync(param1, param2) is non-async method so to call this asynchronously you have to use Task.Run.
I'll recommend to remove .ConfigureAwait(false) as this will actually decrease your performance.

Async and await - difference between console, Windows Forms and ASP.NET

I have been educating myself on async / await use and I think I understood under-the-hood concept. However, most of Channel 9 tutorials, MSDN articles and Stack overflow answers on async / await use GUI-based applications (Windows Forms application) to demonstrate the power of async / await.
However, I noticed a fundamental difference in async / await use in a UI-thread based application vs. regular ThreadPool thread-based applications (e.g. ASP.NET Web Application, Console Application, etc.).
Since, in UI thread-based application, the UI thread is always available (unless the process is stopped explicitly or by Windows), so the ThreadPool thread responsible for executing the code after "await" in any async method, will guarantee to find the UI thread to post the results back (if any).
However, in a console application or ASP.NET Web application, the main thread (in a console application) or the HTTP request (in an ASP.NET web application) must be waiting (at one point of time) until all async operations are completed. So there should be .Wait() and .Result call somewhere after the Async method call, if there is nothing more to work on.
Is this understanding correct? I am not questioning the benefit of having async for I/O bound or network-bound operations (I understand how it's going to increase application scalability).
Since, in UI thread based application, the UI thread is always available (unless the process is stopped explicitly or by Windows), so the ThreadPool thread responsible for executing the code after "await" in any async method, will guarantee to find the UI thread to post the results back (if any).
This is slightly confused. There's no indication that a ThreadPool thread will be required at all.
It's up to the awaitable implementation to determine where to run the continuation, but normally the current synchronization context is used to work out where to run it:
In a console application, there is no synchronization context, so a thread pool thread is used for the continuation.
In a Windows Forms application, when you're running on the UI thread the synchronization context is one which will execute code on the UI thread... so the continuation executes there (unless you use ConfigureAwait, etc...)
In an ASP.NET application, there's a synchronization context specific to ASP.NET itself.
See Stephen Cleary's MSDN article for more details.
It's not clear what you mean by your later question about having to call Wait or Result in ASP.NET or a console app... in both scenarios it may be required, but equally it may not be. It depends on what you're doing really. Don't forget that even a console app can start its own threads and do all kinds of other things - you can write an HTTP server in a console app, for example...

WCF - Duplex channel - Will the callback method within request-reply operation come in thread pool thread?

I am using dual channel with NetNamedPipeBinding. I am using callback methods to give progress to the client. I have couple questions. I am keen to confirm the behavior just to make sure my design doesn't have any flaws.
Will the callback method be invoked on thread pool thread? I looked at the debugger and it is coming from worker thread. Just want confirmation as I didnt see this detail in documentation.
Can I invoke a callback within request-reply operation?
I tried this and its working. But is it recommended/ok to have a callback within request reply operation?
Please note that my service is running with persession instance mode and multiple concurrence mode to have effective throughput for my operations. And the operations are thread safe.
About your question #2:
In my RPC framework design, i contains a CALLBACK-COMMAND in the response message.
that's just like you say "REQUEST-REPLY".

Dispatcher.Invoke 'hangs' during asynchronous read in Windows Service

I've created a Windows service based on the ServiceBase class. In this service I created an instance of the NamedPipeClientStream (m_Stream). After connecting this stream I start an asynchronous read using the BeginRead() method:
m_Stream.BeginRead( m_ReadBuffer, 0, 2, ReadAsyncCallback, m_ReadInfo );
In the callback routine ReadAsyncCallback, which indeed gets called, I call EndRead() for the stream (which gives me the number of bytes read, in this case 2). Next, I want to signal the original thread that the read has been completed. For this I use the Dispatcher.Invoke method:
m_Dispatcher.Invoke( new ReadDelegate( this.OnRead ), bytesRead);
(m_Dispatcher was created in the original thread using System.Windows.Threading.Dispatcher.CurrentDispatcher.)
At this point I expected the OnRead method to get called in the original thread, but it doesn't. The Invoke() method doesn't return, it seems to 'hang'.
I hope someone can help me with this. Please let me know if you need more info, I will try to give it to you asap.
Greetings,
Richard
The System.Windows.Threading.Dispatcher requires a correctly configured SynchronizationContext in order for it to work as you normally expect. When in the context of a WPF application the synchronization context is automatically created for you, however in your Windows Service that does not happen and that's why you see the hang.
Also, aside the synchronization context, since I believe the Dispatcher works in a similar way to the Control.Invoke or BackgroundWorker in Windows Forms, your Windows Service main thread must be pumping a message loop in order for you to be able to inject your call into it.
I have written a blog about how the BackgroundWorker class reacts differently according to the context in which its run (Windows Forms, Console or Windows Service), which you may find to be an interesting read since the mechanism used by that class is similar to the WPF Dispatcher.
Inside BackgroundWorker
Finally, for a more in depth dive into how the synchronization contexts work you should read:
It's All About the SynchronizationContext
The thread that called CurrentDispatcher is probably not pumping messages for some reason. The most likely reason is because it does not have any message pumping mechanism. For Invoke to work correctly the target thread must be specially designed to accept delegate injections. This is usually accomplished by having the target thread spin in an infinite loop waiting for messages to appear in a queue. Another thread would then submit a special message requesting the execution of a delegate. This is all setup automatically on the UI thread of Windows Forms or WPF applications. It will not exist in Windows Service application unless you get it going manually.
I would not attempt to use this delegate marshaling technique (or any technique that synchronously injects a delegate into another thread) anyway. The reason is because it will cause that asynchronous IO callback, which is executing on a ThreadPool thread or IO completion port thread, to block until that marshaled delegate completes. You do not want to tie up the IO in this manner.
Instead you should publish the data that is read from the stream into a shared data structure, like a queue or list, and then have your original thread pick it up on a specific interval. If the original thread is expected to wait for data to be read from the stream then you could setup the producer-consumer pattern. This is pretty easy with the BlockingCollection. The original thread will call Take which will block until an item arrives and the IO callback will publish the data by calling Add.
There are other acceptable ways this could be handled, but calling Invoke is probably not one of them.

.NET threading solution for long queries

Senerio
We have a C# .Net Web Application that records incidents. An external database needs to be queried when an incident is approved by a supervisor. The queries to this external database are sometimes taking a while to run. This lag is experienced through the browser.
Possible Solution
I want to use threading to eliminate the simulated hang to the browser. I have used the Thread class before and heard about ThreadPool. But, I just found BackgroundWorker in this post.
MSDN states:
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.
Is BackgroundWorker the way to go when handling long running queries?
What happens when 2 or more BackgroundWorker processes are ran simultaneously? Is it handled like a pool?
Yes, BackgroundWorker can significantly simplify your threading code for long-running operations. The key is registering for the DoWork, ProgressChanged, and RunWorkerCompleted events. These help you avoid having to have a bunch of synchronization objects passed back and forth with the thread to try to determine the progress of the operation.
Also, I believe the progress events are called on the UI thread, avoiding the need for calls to Control.Invoke to update your UI.
To answer your last question, yes, threads are allocated from the .NET thread pool, so you while you may instantiate as many BackgroundWorker objects as you'd like, you can only run as many concurrent operations as the thread pool will allow.
If you're using .NET 4 (or can use the TPL backport from the Rx Framework), then one nice option is to use a Task created with the LongRunning hint.
This provides many options difficult to accomplish via the ThreadPool or BackgroundWorker, including allowing for continuations to be specified at creation time, as well as allowing for clean cancellation and exception/error handling.
I had ran in similar situation with long running queries. I used the asynchronous invoke provided by delegates. You can use the BeginInvoke method of the delegate.
BackgroundWrokerks are just like any other threads, accept they can be killed or quit, w/out exiting the main thread and your application.
ThreadPool uses a pool of BackgroundWorkers. It is the preferred way of most multi threading scenarios because .net manages threads for you, and it re-uses them instead of creating new ones as needed which is a expensive process.
Such threading scenarios are great for processor intensive code.
For something like a query which happens externally, you also have the option of asynchronous data access. You can hand off the query request, and give it the name of your callback method, which will be called when query is finished and than do something with the result (i.e. update UI status or display returned data)..
.Net has inbuilt support for asynchronous data querying
http://www.devx.com/dotnet/Article/26747

Categories