【问题标题】:Task Cancellation任务取消
【发布时间】:2016-10-20 10:37:54
【问题描述】:

我正在寻找一种方法来取消已经启动的任务,然后使用新的输入数据重新启动相同的任务。

以下是我编写的示例代码,但它不起作用。

private CancellationTokenSource _cancellationTokenSource;
public public async Task DoSomething(string input)
{
    _cancellationTokenSource.Cancel(true);
    _cancellationTokenSource = new CancellationTokenSource();
    try
    {

        Task.Run(async () =>
        {
            //Asynchronous method code here which uses input like database operations.
            await doSomeDataBaseOperationAsync(input);
        }, _cancellationTokenSource.Token);
    }
    catch { }
}

有人可以帮我吗?

【问题讨论】:

  • 取消是手工制作的;您必须检查您的令牌状态以查看是否已请求取消,并尽您所能实际取消。
  • 什么不起作用?从你调用DoSomething 的地方你可以简单地调用_cancellationTokenSource.Cancel(true); 这将取消任务然后再次调用该方法。它不工作吗?
  • cancellationTokenSource.Cancel(true);这段代码在初始化之前,有效吗?
  • 另外,DoSomething 方法中的 cancellationTokenSource 变量是什么?它似乎没有在您的代码块中的任何地方定义。
  • 基本上我的 doSomeDataBaseOperationAsync(input) 仍然使用旧输入执行,然后从新输入开始。

标签: c# uwp task


【解决方案1】:

您需要在您的方法doSomeDataBaseOperationAsync 中进行手动检查,该方法正在异步执行,如下面的代码 sn-p 所示。我通常做的方式是在方法本身开始时检查一次取消令牌源的状态。如果在那之前没有请求取消,那么继续执行整个函数体。

但是没有人可以阻止您在方法中更关键的时刻或里程碑进行检查,例如您可能还想在触发 DB 调用之前重新检查一次取消令牌状态。

注意事项:您只需要确保在方法执行期间多次进行此类检查并返回中途时,您不会离开对象的状态处于不一致的状态。如果您在这种方法中不更改类的任何成员变量,那么您应该很好。

private void doSomeDataBaseOperationAsync(input)
{
   if (_cancellationTokenSource.IsCancellationRequested)
     return; //stop any further processing.
   //do some processing and calculations on the client side
   //.....
   //.....
   //.....
   //make a check again before firing DB request
   if (_cancellationTokenSource.IsCancellationRequested)
     return; //stop any further processing.
   //Do database stuff. cancellation has not been requested. Process the DB request.
}

【讨论】:

  • CancellationTokenSource.Cancel() 事件不会一直传播到整个任务吗?
  • 为什么要在任务中检查这个,提供了取消令牌,它会自动取消,这必须在调用者中检查以异步模式启动的任务的取消。
  • @SurajMittal 你是对的,从外面检查一下IsCancellationRequested
  • @RBT 如果我的doSomeDataBaseOperationAsync() 只包含数据库代码而没有其他内容怎么办?
  • @SurajMittal 您只需在方法体开始执行时检查一次。如果尚未请求取消,请联系您的数据库并触发您的查询。之后您将无法中途停止数据库请求。从您的几个 cmets 我可以判断您正在寻找的东西好像线程/方法应该立即被 CLR 中止取消令牌已设置。如果你期待这样的事情,那是不可能的。 TPL 信奉合作/优雅终止的理念。 Thread.Abort API 现在已成为过去。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多