I'm learning about the AsyncController in ASP.NET MVC and using it with the TPL, but I'm struggling to see its need, I can understand when you would want to run an Action asynchronously to do something like send out an email, but in reality would you ever use it to return a view from an action?
For example if the Action gets some data from a database, which is set to work async, then return a View, if the data fails to retrieve in time will the View not just return with no data in the model?
Would you ever use it to return a view from an action?
The main advantage of asynchrony in ASP.NET is scalability. While the asynchronous work executes, you're not consuming any threads. This means your application will consume less memory and it may be also faster.
If the data fails to retrieve in time will the View not just return with no data in the model?
That depends on you and how exactly will you handle that failure.
Async controllers are used primarily to give up the current thread pool thread to allow other incoming connections to process work while you are waiting for a long running process to complete.
This has nothing to do with pass a view back. The process will still "block" from the end users perspective, but on the server the resources the server needs to respond to incoming requests will not be consumed.
By default, there are 250 thread pool threads per cpu core in an IIS worker process to respond to incoming connections (this can be tuned, but in general you should know what you're doing). If you have to people waiting for long requests to complete, then nobody else will be able to connect to your server until one of them finishes. Async controllers fix that problem.
You can also offload CPU bound work to a dedicated thread when using async controllers, where that was more difficult in synchronous controllers. And, it allows you to perform tasks in parallel. For instance, suppose you have to go out to 10 web sites and retrieve data. Most of the time is spent waiting for those web requests to return, and they can be done in parallel if you are doing things async.
Related
I am in the process of converting a JavaScript-based hybrid app to a native iOS app. When I started developing the app with JavaScript, I was disappointed to find out that if you want to make an HTTP request, you have to do it asynchronously. I tried to get around this in various ways, basically:
var done = false;
$.post(url, data, function() { done = true; });
while (!done) {}
//Continue
But I came to find that this is ugly and just plain bad practice, so I got over it and just did it asynchronously.
So when I started with iOS I was excited with the idea that I might be able to do it synchronously, but again I was disappointed to find that the recommended practices are asynchronous, favoring closures or delegates to handle responses.
My question has two parts:
Why is it such common practice in almost every case for HTTP requests to be made asynchronously instead of synchronously?
Is there a way to make synchronous requests in iOS that isn't ugly or problematic?
Essentially, I've always wanted to be able to do something like:
var response = SubmitHTTPPostRequest(url, data)
Is this not really a thing? I never learned this kind of thing in school, so I apologize if this is a rudimentary question. I've just never understood why this is the way it's typically done.
You need to understand the process from sending a request to getting a response. The request will most likely go through some network adapter, to some server, back to the adapter and then back to your CPU. In general there are no cases where there is only one processor involved, in the case I described are 3 but usually there are more. That means synchronisation as doing all the work in one process is impossible since multiple processors are involved. The path to synchronisation (as already mentioned) is for your current thread to wait. I can not agree that will freeze your UI but will freeze your thread (which will freeze the UI if it is the main thread). Still putting the whole process into another thread which will wait for response will produce many other issues and questions such as "should I create a thread for each request", "memory consumption if responses take too long to return?"...
I can understand you want this synchronisation so you can do the operation in a single method but in the end this is exactly what makes an ugly code. Your method then consists of creating the request, getting response, processing response and processing the data received all in one. This might seem a good idea on the beginning but when this method becomes too long you will want to refractor the code into at least 3 methods which by coincidence is exactly what you need to do with asynchronous request. So to answer your second question: Very unlikely, the asynchronous procedure looks much less ugly.
What you should do and is done in most cases is to create some class that handles your requests and responses so from the UI part of your code you only need to do a single call. Lets say you have a table view on which you will display a list of your friend received from some social network. When you first come to this list you would like some activity indicator view to notify the user the data is loading, then send some asynchronous request to get the friends not caring when and if the response will return but when the response is received you simply remove the activity indicator and reload the table view with new data received. Now I hope you can imagine this is a very elegant code and by doing so you enable the user to be able to cancel the request by pressing back.
So the main reason for doing request asynchronous is not to block the threads because that may generate multiple issues or even blocking the main thread which will block the UI and if the main thread is blocked for too long the application will be killed in iOS (watchdog). And the reasons to do synchronisation? Well, in long term I can not think of any, you should always break operations into many methods and use callbacks.
First of all, you should be very clear with synchronous and asynchronous terms.
When Synchronous request sent, caller has to wait for the request to complete the process.
And Asynchronous request don't wait for finish.
As per stack overflow answer , i have read once :
When an HttpHandler is called, a thread pool thread is used to run that request and the same thread is used to process the entire request. If that request calls out to a database or another web service or anything else that can take time, the thread pool thread waits. This means thread pool threads spend time waiting on things when they could be used to process other requests.
In contrast, when an HttpAsyncHandler, a mechanism exists to allow the request to register a callback and return the thread pool thread to the pool before the request is fully processed. The thread pool thread starts doing some processing for the request.At that point, the thread pool thread that was processing the HTTP request is returned to the pool to process another HTTP request.
Your Answers :
1.Because , asynchronous request do not wait for task to complete. send request and while in the same time thread can perform other task without waiting. i use ASIHttpRequest in my ios app.
2.We can send request synchronously but not common this days in practice.
I Have a quick question about async Controller and Actions in ASP.Net MVC 4+ (using the async/await programming model returning a Task ).
What do i risk if all my actions are async even if the underline operations are not IO Bound (for example slow web service or network communication ) and can be CPU Bound. I mean all my actions will be async no matter what code is int it . I Hope i'am clear.
Will be performance problems due to synchronisation context overhead or any other significant overhead for a public website that can have a lot of simultanous users ?
Thank you for your futur answers.
What do i risk if all my actions are async even if the underline operations are not IO Bound (for example slow web service or network communication ) and can be CPU Bound.
This is exactly what you don't want to do.
Consider what happens with a synchronous action: the request comes in, ASP.NET allocates a thread for that request, and that thread executes the action. When the action is complete, that same thread sends the response.
Now consider what happens if you "offload" an action's CPU-bound work to the thread pool (e.g., Task.Run). The request comes in, ASP.NET allocates a thread for that request, and the thread starts executing the action. When the thread hits Task.Run, it allocates another thread from the thread pool to execute the CPU-bound code. Then the asynchronous action method hits the await for that task, so the original thread is returned to the ASP.NET runtime. The other thread then finishes the work and continues on to send the response.
So, you're doing more work for every request if you have an asynchronous action that pushes CPU-bound work to the thread pool. You should never do this on ASP.NET.
I explain this in more detail on my blog.
I don't think you will run into any problems for a simple app since the async workers are running off a pool of threads with a limit number of threads. But what you may run into is a condition where the client HTTP threads are waiting on the asyn response and it exceeds a network gateway timeout. For instance, amazon ELB have a 60 second timeout. So clients can be disconnected while the async task is still running. If that happens a lot then you could end up with a lot of async tasks running and completing with no client to respond to. That would be an unfortunate condition because your clients are not getting data and your server is working for nothing.
One thing I would consider is whether or not you need async calls. I would suggest tuning up your service calls and making sure they are fast enough to address load instead of making the front end async as a workaround for the latency. For instance, using caching. Just a suggestion.
Hope it helps.
I was looking at ASP.NET MVC 5 templates and I have notice that many of the actions and marked as async:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { }
When should I do this on an MVC action? When it contains access to a database?
If I call a repository inside the action should I also use Task to make it async?
The core of your questions is: When should I make my MVC actions async? See http://blogs.msdn.com/b/rickandy/archive/2009/11/14/should-my-database-calls-be-asynchronous.aspx for a good discussion of the issue. He talks about the database only, but his points carry over.
Essentially, almost never call the database in an async way.
For database applications using async operations to reduce the number of blocked threads on the web server is almost always a complete waste of time.
Don't be detracted by people telling you to always use async IO if possible. Async is all the rage right now. Lot's of irrational advice is being spread.
Entity Framework 6 (used by default with MVC 5) now supports async database calls, so the action method signatures have been update to reflect async being used. The simple answer is that whenever you have a task that could potentially involve waiting, use async. Hopefully, your database queries won't take long enough to roundtrip to actually benefit much from async, but if your database falls down or is being hammered particularly hard, it'll at least help to not deadlock IIS in the process.
Here's an article what lists some uses cases when using tasks may have benefit and some uses
cases when may have the opposite effect.
The answer is not this simple every time, this is why the last point about testing.
Quote from http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4
In general, use synchronous methods for the following conditions:
The operations are simple or short-running.
Simplicity is more important than efficiency.
The operations are primarily CPU operations instead of operations that involve extensive disk or network overhead. Using asynchronous
action methods on CPU-bound operations provides no benefits and
results in more overhead.
In general, use asynchronous methods for the following conditions:
You're calling services that can be consumed through asynchronous methods, and you're using .NET 4.5 or higher.
The operations are network-bound or I/O-bound instead of CPU-bound.
Parallelism is more important than simplicity of code.
You want to provide a mechanism that lets users cancel a long-running request.
When the benefit of switching threads out weights the cost of the context switch. In general, you should make a method asynchronous if
the synchronous method waits on the ASP.NET request thread while doing
no work. By making the call asynchronous, the ASP.NET request thread
is not stalled doing no work while it waits for the web service
request to complete.
Testing shows that the blocking operations are a bottleneck in site performance and that IIS can service more requests by using
asynchronous methods for these blocking calls.
I got the following problem, I want to execute a block of code that might take a while.
It would be a bad user experience if the user has to wait for it to finish. So I though of using a thread.
[HttpPost]
public ActionResult methode(Model model){
Task.Factory.StartNew(() =>
{
// Do a block of code that takes a while
});
return Json(new
{
succes = GetValue()
});
}
When debugging you can clearly see that the thread is being executed and that the return code is reached.
Problem I got here is that the actual return takes place when the thread is done. ( so I am not gaining any speed here.)
Why is that? And how do I make it work?
Thanks in advance!
The way you have done it above won't work because as you have observed, you have await the task and then return, so effectively it's a synchronous operation from the user's point of view and they are stuck waiting for the server to respond with the actual results of the work.
There are a couple of ways to do this though, it depends on what the nature of the task is. If this is something that generates data that the user might want to come back to later on and download e.g a report that can take a while to generate:
Using an asynchronous controller, kick off the task and keep a record on the server side via some unique identifier, and then return immediately with that identifier.
A client-side script is then triggered to poll every N seconds via an Ajax call, to see if the work is complete on the server side
However if the app pool gets recycled in IIS during the running of this thread, the work is lost and you haven't really got a way to control this
Better yet kick off the long running task in a separate process and then the client can poll every few seconds(or use SignalR from the server side to push) for when the job is done.
A typical way to achieve this is to push a record of the work to be done into a Queue and then return some kind of identifier to the client.
Your separate process can just be running all the time and monitoring the queue for new work to do, it can then update a database or cache with the results of the work.
Meanwhile the client is polling (or SignalR is pushing whereby your signalr hub checks every few seconds and pushes the job status back to the client) to see if that particular "job" is completed.
This way you are not at the mercy of the web server process going down and trashing all your threads, plus you gain much better control over cases where you need to defer jobs, spread the load over multiple servers, etc.
If on the other hand this is data that just takes a while to calculate but is only going to be available to the user on-screen, and you don't allow the user to leave the current page whilst waiting for the results, then just use a properly asynchronous Ajax call from the client-side!
I have a particularly long running method that I need to execute from my controller. The Method is in it's own Model. I am using an async controller, and I have the method setup using asyncFunc library to make it asynchronous. I have also tried invoking it on it's own process. The problem is I want to controller to go ahead and return a view so the user can continue doing other things as the method will notify the user it is completed or has any errors via e-mail.
The problem is even thogh it is an asynchronous method the controller will not move forward to return the view until the process is done. 15+ mins. and if you navigate to a different page the method stops trying to execute.
so how can I get the method to execute as a worker and free up the controller?
Any Help would be greatly appreciated.
all the best,
Chase Q, Aucoin
Use ThreadPool.QueueUserWorkItem() as a fire-and-forget approach in the ASPX page.
Do the long-running work in the WaitCallback you pass to QUWI.
when the work is complete, that WaitCallback can send an email, or whatever it wants.
You need to take care to handle the case that the w3wp.exe is stopped during the 15 minute run. What will you do if the work is 2/3 complete? Some options are, making the work restartable, or just allowing the interrupted work to be forgotten.
Making it restartable might mean, when w3wp.exe restarts, your ASP.NET logic makes sure to begin again, any work that was interrupted. It might mean that your ASP.NET logic sets "syncpoints" so that it knows where to restart.
If you want the restartable option, you might think about Workflow, which is specifically designed for this purpose - maintaining state of long-running workflows, restarting automatically, and so on. If you use Workflow, you can set it to run asynchronously, and you may decide you do not need QueueUserWorkItem.
see also:
Moving a time taking process away from my asp.net application
the Workflow Foundation tag
This will help > http://msdn.microsoft.com/en-us/library/ms227433.aspx
It is the standard way of running a background process on the server in the .NET stack.
I don't know why, but I still live in conviction that this should not be done. Executing background threads in ASP.NET smells. You will also steal threads from ASP.NET thread pool which is controlled by IIS. It can decide that something is wrong with your worker process and restart it any time just to keep memory consumption, processing time consumption or thread consumption low. If you need background logic create custom NT service and call the process on that service either via old .NET remoting or WCF.
Btw. approach I described is used frequently in commercial applications and those which doesn't use it often self-host the whole web server.