I'm writing a small internal web app.
I need to do a very long operation (which can take about an hour) at the press of a button and let the user know once the operation completes with its result.
In other words, I need the button to start the async operation and refresh the view with the results once it is finished (after about an hour run).
Edit: The operation could use some sort of a refresh mechanism in the View. The result can be sent to the view after a small lag (doesn't have to refresh realtime)
You could use SignalR, but that might be a little bit overkill for this. Another option is to set up another controller action which checks if the task has been completed. Then, on the client side, you could use jQuery to make ajax requests to that controller action. When the action comes back as complete you can show an alert or otherwise update the page.
$.ajax({
type: 'GET',
url: http://mysite.info/tasks/checkComplete/5,
success: function (response) {
if (response == 'true') {
alert('Task complete');
}
}
});
As for what happens on the server side, I don't think this is a case where I would use async/await. If your task is really going to be running for an hour I have a feeling you're going to run into timeout issues, etc. I would have a controller action which is used to start the task, but all it does it put the request to start in the database. I would then have an external "worker" which checks for requests in that database and performs the tasks. Once the task is complete it would update that database entry to mark it as complete. Then the "CheckComplete" controller action from my example above could check the database to see if the task is in fact completed.
As suggested in the comments, I recommend you to take a look at SignalR, it's not that hard to implement.
You'll have to implement a server on your website, send a message to the server when your long operation is complete, and refresh your view when the message is received.
The tutorials from Microsoft should be clear enough for that.
A low tech solution from the age way before AJAX and WebSockets was to simply continually write data to the response (usually a progress report).
So instead of doing the work asynchronously, you would call something like
Response.Write("<script>reportProgress(" + progress + ");</script>");
Response.Flush();
once in a while. It has its issues, but it might still be a good way if you have to support weird platforms or very old browsers.
Ummm,
I will try to create flag into the server when finished the work.
In the MVC you can will create a TIMER obj that check, for example each minute, if the server has finished the work, and launch this timer in a new thread that not block the app.
(sorry, for my english).
Related
Primary issue: There's a block of code that I want to execute in the background. Please read further to understand what I mean by "background".
I am trying to perform external data posting through a an asynchronous/non-blocking thread. The main idea is that the user who submits the form need not wait for the external requests to complete.
The current flow is like this:
User submits a form, with data
Action processes the data performs internal steps like database updates, email notifications etc, and also uses external resources to post data using API
User is taken to the "thank you page"
I am trying to decouple the UploadFilesToAmazonAWSAndDropBoxAndFlickrAndGoogleDrive from the regular user flow, as in the current setup, the user is waiting for the external API to complete. How to make UploadFilesToAmazonAWSAndDropBoxAndFlickrAndGoogleDrive run in a background thread?
Edit: Posting a rough outline of the code that I am trying to fix
[HttpPost]
public ActionResult Index(FormCollection fc)
{
//database operations,
InsertIntoDatabase(fc); //takes 1 second
//3rd party posting
//Takes about 30 seconds.
//Why it takes 30 seconds is obvious. Please let me know if this isn't obvious.
UploadFilesToAmazonAWSAndDropBoxAndFlickrAndGoogleDrive(fc);
//email operations
SendEmails(fc); //takes 1 second
//User is taken to Thank you page after 32 seconds. I want to reduce the time to 2 seconds
return View("ThankYou");
}
Based on your edited scenario and target, the following high-level options might work to get you there.
You could use Task.Run to start a background thread for your PostDataToExternalResources method, but you will still need to manage any exceptions etc on your side. Additionally, I wouldn't pass the form collection off to that method if you do it this way, just keep in mind that you wouldn't have guaranteed results
You could use something like HangFire to turn that process into a background job, which has its own durability etc. I again wouldn't pass the FormCollection in, but it could have better durability.
Since it seems that viewing the "Thank you" page is not dependent upon the tasks completing, I'd look at something durable/executable like HangFire for consistency and ease of management
I have a piece of functionality in my web application that kicks off a long running report on my server. Currently, I have an ajax method on my client that is constantly running to check if the currently running report is complete. It does this by repeatedly calling a method that queries the database to determine if a given report's status has changed from Running to either Error or Complete. Once the report is finished, I perform an ajax load to get the data.
I'm looking at implementing SignalR to add some additional functionality to other pages, and I figured this would be a good test case to get things going. My main concern is how to alert the client when the report is complete. Using SignalR, I can simply say something like:
public class ReportHub : Hub
{
public async Task ReportComplete(string userId, ReportRunStatus guid)
{
await Clients.User(userId).SendAsync("ReportComplete", guid);
}
}
However, I want to try to avoid putting a long running loop on the server as I'm afraid this could degrade performance as operations scale up. Is there a better way to handle checking the report status and alerting clients than simply polling until completion? Or is there some easy way to constantly be looking at the table and alerting on completed reports?
I have one HTTP post call in angularjs which takes around 7-8 secs to complete the task. The url is action method of one controller in MVC. As it is taking a lot of time I don't want my user to wait for this operation but can navigate to any other page or even can continue with different operations on the same page. once the operation gets complete, it will notify user for either the success or failure.Currently any other http post waits for this post to get complete before showing it's respective result. I need help in what can be done for this scenario. What is the best approach? I checked this below link and I see some suggestions. Will it be helpful? link- http://tech.pro/tutorial/1252/asynchronous-controllers-in-asp-net-mvc
AngularJS Code-
$http({
url: key_Url_Generate,
method: Post,
params: $scope.PlanDetails
}).then(function (result) {
//Notify user for success or failure
}
Controller Action Method-
[HttpPost]
public ActionResult GenerateLtdQuote(LTD_PlanDetailsVM ltdPlanDetailsVM)
{
// time consuming operation here
}
No, async, at least in terms of C#, merely allows the thread to be returned to the pool while it is in a wait state, i.e. waiting for something like an external service to respond. It does not make the action return quicker. In fact, if anything async can make things slower, as it adds overhead. If the endpoint being hit by your AJAX does anything that puts the thread in a wait state, where it's doing nothing but waiting for some external process to complete, then you should use async on it, but only because it allows the server to more efficiently use resources. It won't make anything happen any quicker, though.
Async, in terms of JavaScript, is a little different, as JavaScript process will continue. That is why you have a callback for AJAX requests. When whatever resource is being accessed remotely finally responds, the callback will be invoked, but other things can still happen in the meantime. This actually makes your question more confusing, though, because by using AJAX, your page should not be blocked at all and the user should still be able to interact with the page and do whatever they want. The only way this wouldn't occur is if you're running AJAX synchronously, which is actually a little hard to do by accident, and should definitely be avoided.
my program does a long postback and I put some message onscreen that it's "Working". Now I want to query with AJAX in parallel to update that status (e.g. "20% done...").
However it turned out that during postback no parallel calls to any webmethods are executed, these are delayed. So Javascript makes these calls (not so regularly) but they do not receive a reply before the whole PostBack ends (that renders the whole attempt of updating progress status unusable).
Is there a way to make parallel queries to IIS / ASP.NET application work?
I use ASP.NET 4.0 and Visual studio 2010 alongside with development server component
Thanks in advance!
You could take a look at using SignalR for this sort of operation. Check out http://www.signalr.net for more info.
This will allow you to start a long process and then have progress of this operation sent back to the client.
Scott Hanselman provides a working example of how to do this sort of thing on his blog. See here http://www.hanselman.com/blog/SolvingTheShakespeareMillionMonkeysProblemInRealtimeWithParallelismAndSignalR.aspx
Note though that his blog post was using an older version of SignalR so the code would require some API changes to work with the latest version.
I was interested as well and found next explanation:
You can’t make AJAX calls during a postback, this is because during a
postback the page is destroyed in the client, including the callback
functions of the AJAX call, control goes to the server to obtain the
new contents for the client, when control returns to the client
everything is reconstructed there, and I’m supposing this is when the
AJAX call is being made.
Another option would be starting the process with an AJAX call instead of a Postback.
So, the first call would start the process on another thread on the server. The following calls would only check the progress with some sort of shared variable with the processing thread. When the process is finished, you can make a postback to refresh the data on the page if needed.
When i saw the first news about await, i was very excited and i thought many ways of using it.
One of these is to use it in my web framework to hide the asynchronous aspect of client/server exchanges like it's done in several frameworks.
So here is the deal:
I would like to write things like that:
{
Page p = new Page();
FormResponse response = await p.Show();
var field1 = reponse.inputField["input1"];
...
}
I would like the dev to be able to write this code on the server. As you guess p.Show() write in the HttpResponse the html code displaying the page with the form, and send the response to the client, so, the thread is
killed and i never reach the next instruction (FormResponse response =).
So here is my question:
Is there any way of doing such a thing ? I know await cut the code, pack it in a continuation, make the closure for us, and store it somewhere to call it back when p.Show() is done.
But here, the thread is going to be killed, and this is my code which recieve the submit response from Page which has to deal with it. So i have to restore the continuation that "await" created and execute it myself.
Am i getting high or is it possible ?
Edit : additional infos
I can explain a bit more, but we need an example.
Imagine you want to make an async call to a webservice, you just use await and then call the webs.
A webs doesn't display any page, it returns pieces of information and you can continue the next instructions, so with a webs we have : Client -> Server A [-callwebs-> Server B ->] Server A -> Client.
Now, imagine a webs wich has to display a user interface to grab some information from the user, we can call this kind of webs a UIwebs (a reusable interface called by several webapp),
it displays the ui, grabs the info, and sends it back to the caller.
So with a UI webs we have : Client -> Server A [-response_redirect-> Client -get-> Server B (here is the UIwebs, the client inputs whatever) -response_redirect-> Client -get-> ] Server A -> Client
What i put between brackets has to be handle in the way by the developper :
so for a classic webs, i can imagine the asynchronous page is "sleeping" waiting the webs to response, but with a UI webs we have to response à redirect to the client, so the page is done for asp.net, and SynchronizationContext says that there is no more async instruction to wait for.
In fact, my need here is the same as turning on the web server, and sending a request to it wich coule restore everything needed to execute the code just after the await.
Regards,
Julien
I'm not sure what the problem is.
If you have, e.g., ASP.NET asynchronous pages, then any top-level (async void) function will properly notify ASP.NET that the page is incomplete and release the thread. Later, the continuation will run on a (possibly another) thread, restore the request context, and finish the request.
The async design was carefully done to enable this exact behavior. In particular, async void increments the outstanding asynchronous operation count in SynchronizationContext, as I described in a recent MSDN article.
If you're running your own host (i.e., not using ASP.NET), then you'll have to implement SynchronizationContext. It's non-trivial but not extremely hard, either. Once this is done, async and await will "just work". :)
Updated answer in response to edit:
Keep in mind that await/async are just syntactical sugar; they don't enable anything that wasn't possible before - they just make it easier.
If I understand your situation correctly, you want a web service to return a UI and then respond to it. This is an inversion of how HTTP works, so you'd have to do some funky stuff with viewstate. I'll think about it...