在我看来,我有两个按钮,一个调用Start()动作,另一个调用Stop()。这是控制器的样子:
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);
}
}
但是当我单击停止按钮时,只有在Start完成后才会调用Stop动作。我该如何停止行动?
答案 0 :(得分:2)
引自Pro .NET Performance:
一书取消已经执行的工作需要来自执行该工作的代码的合作。但是,尚未开始执行的任务可以完全取消,不会产生任何恶性后果。
这意味着在Task
lambda中你需要检查工作是否已被取消并采取相应的行动。例如:
if (cts.IsCancellationRequested) return;
您是否在检查取消请求?
更新
检查需要在// Do stuff
部分的某个地方。因此,例如,如果您将复杂的多部分计算作为一项任务运行,您必须循环数百个项目,进行一些处理并在结束时返回一些结果,您可以在循环的每次迭代开始时检查取消
或者另一个例子,如果您在任务中使用了支持取消的API(例如HttpClient.GetAsync
),那么您必须将CancellationToken
传递给该API适当的重载。
答案 1 :(得分:0)
我需要使用
[SessionState(SessionStateBehavior.ReadOnly)]
允许我的控制器异步处理请求。由于我使用的是MVC 2并且该属性不可用,因此我必须创建一个自定义路由处理程序。 Serdar对这个问题的回答帮助了我:Disable Session state per-request in ASP.Net MVC