Async Controllers (MVC), a long process with "stops",

I am interested in a lengthy process, I want to update the interface as soon as the results begin, and not wait for its completion.

How can i do this? I read about Async controllers, but they have nothing built in for this purpose.

Just store the results in the Application / Session object when the results come in and use client-side polling? I can think of several ways that may go wrong (for example, the user closes the page, and the object remains in the Application object forever - must control the expiration of this object on its own, additional server load for polling, etc.).

Any thoughts?

thanks

+3
source share
3 answers

I recently tried to solve something like this (I am reporting real-time from the server’s long-term operation to the client), and SignalR turned out to be ideal for this situation.

Basically, this is a library that stores long polls and web sockets, using (transparently) everything that is available on the server and client.

I have only good experience with him so far.

+4
source

You can run a long-running task using ThreadPool.QueueUserWorkItem, and it can update the state in the application / session that the user can poll. As you indicated, that has some problems with life. In addition to what you specified, the application can recycle, but perhaps this is normal.

What is the logical area of ​​this operation? Is this a long-term task like a system so that someone / many people need to request progress? Or is it a long-running task on behalf of a specific user? If this is the last, then it is normal, if it is the time of the user session, etc. If this is the first, you need to be more durable. for example, you can save a task request, status, and progress to a database. Thus, when you restart the application, he can simply choose where he is, and it can be easily requested by anyone (the decision point if the task is a system level).

Final consideration of whether you will ever have multiple web roles (web farm / cluster). If it is ever a consideration than a DB or even a separate role / service of a worker, it becomes more appropriate.

Thus, all this comes down to the type of task for which it is necessary, who should control it and what are the requirements for durability. If this is just a custom task, keep it simple, queueuserworkitem and session state.

+1
source

This article describes what you need, simply and without a SignalR signal:

ASP.NET MVC 3: Async jQuery Progress Indicator for Long-Term Tasks

Controller:

public class HomeController: controller {private static tasks IDictionary = new dictionary ();

public ActionResult Index() { return View(); } public ActionResult Start() { var taskId = Guid.NewGuid(); tasks.Add(taskId, 0); Task.Factory.StartNew(() => { for (var i = 0; i <= 100; i++) { tasks[taskId] = i; // update task progress Thread.Sleep(50); // simulate long running operation } tasks.Remove(taskId); }); return Json(taskId); } public ActionResult Progress(Guid id) { return Json(tasks.Keys.Contains(id) ? tasks[id] : 100); } 

}

View:

 <script type="text/javascript"> function updateMonitor(taskId, status) { $("#" + taskId).html("Task [" + taskId + "]: " + status); } $(function () { $("#start").click(function (e) { e.preventDefault(); $.post("Home/Start", {}, function (taskId) { // Init monitors $("#monitors").append($("<p id='" + taskId + "'/>")); updateMonitor(taskId, "Started"); // Periodically update monitors var intervalId = setInterval(function () { $.post("Home/Progress", { id: taskId }, function (progress) { if (progress >= 100) { updateMonitor(taskId, "Completed"); clearInterval(intervalId); } else { updateMonitor(taskId, progress + "%"); } }); }, 100); }); }); 

});

0
source

All Articles