In my view I have two buttons, one calling the Start() action and one calling Stop(). Here is what the controller looks like:
public class TestController : AsyncController
{
public static CancellationTokenSource cts = new CancellationTokenSource();
public void StartAsync()
{
cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
AsyncManager.OutstandingOperations.Increment();
AsyncManager.Parameters["task"] = Task.Factory.StartNew(() =>
{
try
{
while() {
if (cancellationToken.IsCancellationRequested)
break;
// Do stuff
}
}
finally
{
AsyncManager.OutstandingOperations.Decrement();
}
}, cancellationToken);
}
public ActionResult StartCompleted(Task task)
{
try
{
task.Wait();
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(new { success = false }, JsonRequestBehavior.AllowGet);
}
}
public void StopAsync()
{
cts.Cancel();
}
public ActionResult StopCompleted()
{
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
}
I needed to use
[SessionState(SessionStateBehavior.ReadOnly)]
to allow my controller to handle requests asynchronously. Since I'm using MVC 2 and that attribute is not available, I had to create a custom route handler. Serdar's answer on this question helped me with that: Disable Session state per-request in ASP.Net MVC