无法通过CancellationTokenSource.Cancel()取消任务

Mil*_*vic 3 c# multithreading task task-parallel-library

我无法阻止任务.首先,我刚开始使用任务.以前,我一直在使用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;
Run Code Online (Sandbox Code Playgroud)

这是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!" });
}
Run Code Online (Sandbox Code Playgroud)

现在,当这个动作第一次被击中时,没有任何反应.然后我第二次要求取消.现在,token.IsCancellationRequested说"true",所以token.Cancel()必须做一些事情.但是发布.Status仍然是"正在运行".它会保持这种状态直到它完成,然后它是"RunToCompletion".

所以,我要求取消任务,但它没有被取消.

也许我做错了什么或者我错过了一些明显的东西,但我无法看到/理解为什么它不会取消.

也许有人可以解释一下?

问候.

Ser*_*rvy 7

取消令牌不会立即导致任务的委托在正确的位置停止执行.支持(Abort通过线程完成)会导致各种各样的不良,包括未正确清理的对象,由于执行停止,因为执行停止在逻辑上被视为原子的操作等,因此违反了不变量等.

你需要做的是让正在执行的函数看看CancellationToken并定期验证它是否还没有被取消.除了将令牌传递给StartNew您之外,还需要将其传递给DoPosting方法.然后,该方法需要定期调用token.ThrowIfCancellationRequested();方法中的某些位置,如果确实请求取消,则应该停止该位置.

请参阅如何取消不可取消的异步操作?进一步阅读.