繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM