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

本文关键字:取消 任务 Cancel CancellationTokenSource | 更新日期: 2023-09-27 18:17:26

我无法停止一个任务。首先,我刚开始使用任务。以前,我一直在使用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"。

所以,我请求取消一个任务,但是它没有被取消。

也许我做错了什么,或者我错过了一些明显的东西,但我就是看不懂/理解为什么它不取消

也许有人能给点启示?

致意。

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

取消令牌不会立即导致任务委托在当前位置停止执行。支持它(通过Abort通过线程完成)会导致各种各样的问题,从对象没有被正确清理,由于执行在逻辑上应该被观察为原子的操作中途停止而违反不变性,等等。

您需要做的是让正在执行的实际函数查看CancellationToken并定期验证它没有被取消。除了将令牌传递给StartNew之外,还需要将其传递给DoPosting方法。然后,该方法需要在方法中适合停止(如果确实请求取消)的地方周期性地调用token.ThrowIfCancellationRequested();

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

我想你可能对CancellationToken期待太多了。关于任务,我认为CancellationToken仅在确定是否在任务可用的插槽时启动任务时使用。一旦任务启动,当CancellationToken被取消时,任务框架就不能简单地中止委托调用。为了完全取消这样的事情,必须编写由任务框架(DoPosting)调用的代码,使其能够识别CancellationToken,并且必须在代码中的适当位置直接检查该令牌的状态。