[英]Cannot cancel a task via CancellationTokenSource.Cancel()
我无法阻止任务。 首先,我刚开始使用任务。 以前,我一直在使用delegate.BeginInvoke()在后台运行,但这次我需要停止后台执行,如果需要的话。 所以我切换到了任务。 这是我的代码:
CancellationTokenSource token = new CancellationTokenSource();
Task posting = Task.Factory.StartNew(() => DoPosting(docs, session), token.Token);
HttpRuntime.Cache[session.ToString() + "_token"] = token;
HttpRuntime.Cache[session.ToString() + "_task"] = posting;
这是ASP.NET MVC,所以我在HttpRuntime.Cache中存储了持久的东西。 用户可以通过此操作取消操作:
public JsonResult StopPosting(string session)
{
CancellationTokenSource token = (CancellationTokenSource)HttpRuntime.Cache.Get(session.ToString() + "_token");
Task posting = (Task)HttpRuntime.Cache[session.ToString() + "_task"];
token.Cancel();
return Json(new { Message = "Stopped!" });
}
现在,当这个动作第一次被击中时,没有任何反应。 然后我第二次要求取消。 现在,token.IsCancellationRequested说“true”,所以token.Cancel()必须做一些事情。 但是发布.Status仍然是“正在运行”。 它会保持这种状态直到它完成,然后它是“RunToCompletion”。
所以,我要求取消任务,但它没有被取消。
也许我做错了什么或者我错过了一些明显的东西,但我无法看到/理解为什么它不会取消。
也许有人可以解释一下?
问候。
取消令牌不会立即导致任务的委托在正确的位置停止执行。 支持(通过线程Abort
通过线程完成)可能会导致各种不良,包括未正确清理的对象,由于执行停止,因为执行在逻辑上被认为是原子的操作,等等而违反不变量,等等。
你需要做的是让正在执行的函数看看CancellationToken并定期验证它是否还没有被取消。 除了将令牌传递给StartNew
您还需要将其传递给DoPosting
方法。 然后该方法需要定期调用token.ThrowIfCancellationRequested();
如果确实要求取消,那么在该方法中适当停止的地方。
请参阅如何取消不可取消的异步操作? 进一步阅读。
我想你可能期待过多的CancellationToken。 关于任务,我认为CancellationToken仅在确定当任务的插槽可用时是否启动任务时使用。 任务启动后,任务框架不能简单地在取消CancellationToken时中止委托调用。 为了完全取消这样的事情,必须编写Task框架(DoPosting)调用的代码以了解CancellationToken,并且必须直接在代码中的适当位置检查该令牌的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.