Running a task in the background, but returning a response to the client in an ASP MVC web application

I am trying to implement functionality where SQL Server has a stored procedure that must be called from an ASP MVC application and processed in the background (it may take a lot of time because it calls a remote remote remote procedure to process the Excel file stored on the server). But the response of the last HTTP request should be returned to the client, so the user interface will not hang waiting for processing.

I tried so many different ways, but the user interface is still not responding immediately.

I tried BackgroundWorker , but this did not allow the main thread to respond to the client before it was completed, I also tried:

 Thread.QueueUserWorkItem(delegate { //method which performs stored procedure calls// }); 

It still does not return a response, and HttpContext.Current not available in the background thread.

Perhaps there is a way to start background processing, pause it so that the main thread can return a response to the browser, and then resume the background thread so that all processing with calls to the stored procedure?

Did I miss something?

Can someone please let me know how I can solve this problem? It would be very grateful.

+7
multithreading c # asp.net-mvc
source share
4 answers

What I did and it works fine in my case. I'm not sure about the effectiveness, but it works great. Thus, I put the code that calls the stored procedure calls into a separate thread, so that the main thread terminates when background calls are processed in a separate thread and successfully complete after some time. At the same time, the user interface is accessible, so the user can make another request, which will also be processed in the same way. I tested three queries. One by one it overlaps, which means that when the first request was processed in the background, I presented another and another. The user interface responded immediately and all work was completed.

 // ...main thread is working here //put a call to stored procedure on a separate thread Thread t = new Thread(()=> { //call stored procedure which will run longer time since it calls another remote stored procedure and //waits until it done processing }); t.Start(); // ...main thread continue to work here and finishes the request so it looks for user as the response is coming right away, all other stuff is being processed on that new thread so user even doesn't suspect 
+6
source share

I will give Stephan Clearys an excellent article :

When using async on the server side (for example, with ApiController), you can process each web request as an asynchronous operation. But when you give in, you only get the web server thread pool, not the client. HTTP allows only one response, so a response can only be sent after the request is complete. p>

Basically, this does not comply with the HTTP protocol, where each request has only one response.

This can be achieved with several calls to the ASP.NET service, where the request immediately returns a unique identifier that the client can request several times to make progress. You can take a look at SignalR to help with this implementation:

What is the SignalR and Real-time Feature? This is an opportunity to have your server code for distributing content to connected clients, as it happens, in real time.

+2
source share

There is part1 and part2 article by Dino Esposito describes how to achieve your survey using the client-side timer and controller actions. You basically serialize access to the workflow controller method, which returns the status of the task and completion data. However, this can be a bit chatty if you are going to perform only one or two lengthy processes.

+2
source share

If the response to the client does not depend on the result of the background process (i.e., it starts the process in the background and does not wait for its user interface), you can use Revalee (an open source tool) to perform the background task.

The user interface will request this route ...

 public class ForegroundController : Controller { public ActionResult InitiateBackgroundTask() { // The absolute URL that will be requested on the callback. var callbackUri = new Uri("http://localhost/BackgroundTask/Callback"); // The information that will be needed to initiate the background task. object state = "Any object"; this.CallbackNowAsync(callbackUri, state) // ... your controller will now return a response to the browser return View(); } } 

Background work will be done in this controller ...

 public class BackgroundTaskController : Controller { [AllowAnonymous] [HttpPost] [CallbackAction] public ActionResult Callback(Guid callbackId, object state) { // Perform the background work // ... insert your background task code here ... // Return a status code back to the Revalee Service. return new HttpStatusCodeResult(HttpStatusCode.OK); } } 

Revalee Project Site

0
source share

All Articles