我无法停止一个任务。首先,我刚开始使用任务。以前,我一直在使用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。所以我在httprtime . 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!" });
}
现在,当这个动作第一次被击中时,什么都没有发生。那么我请求第二次取消预定。现在,令牌。IsCancellationRequested说的是"true",所以token.Cancel()一定做了什么。但发布。状态仍然是"运行中"。它将保持这种状态,直到它完成,然后是"RunToCompletion"。
所以,我请求取消一个任务,但是它没有被取消。
也许我做错了什么,或者我错过了一些明显的东西,但我就是看不懂/理解为什么它不取消
也许有人能给点启示?
致意。
取消令牌不会立即导致任务委托在当前位置停止执行。支持它(通过Abort
通过线程完成)会导致各种各样的问题,从对象没有被正确清理,由于执行在逻辑上应该被观察为原子的操作中途停止而违反不变性,等等。
您需要做的是让正在执行的实际函数查看CancellationToken并定期验证它没有被取消。除了将令牌传递给StartNew
之外,还需要将其传递给DoPosting
方法。然后,该方法需要在方法中适合停止(如果确实请求取消)的地方周期性地调用token.ThrowIfCancellationRequested();
。
参见如何取消不可取消的异步操作?进一步阅读
我想你可能对CancellationToken期待太多了。关于任务,我认为CancellationToken仅在确定是否在任务可用的插槽时启动任务时使用。一旦任务启动,当CancellationToken被取消时,任务框架就不能简单地中止委托调用。为了完全取消这样的事情,必须编写由任务框架(DoPosting)调用的代码,使其能够识别CancellationToken,并且必须在代码中的适当位置直接检查该令牌的状态。