正确的模式以处理取消令牌源 [英] Correct pattern to dispose of cancellation token source

查看:42
本文介绍了正确的模式以处理取消令牌源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑一个方案,其中您需要完成一些异步工作,并且可以在即发即弃模式下运行它.此异步工作能够侦听取消,因此您将取消令牌传递给它以便能够取消它.

Consider a scenario where you have some asynchronous work to be done and you can run it in a fire and forget mode. This asynchronous work is able to listen for cancellation and so you pass it a cancellation token in order to being able to cancel it.

在给定的时间,我们可以决定使用正在使用的取消令牌的取消令牌源对象来请求进行中的活动的取消.

At a given moment in time we can decide to request the cancellation of the ongoing activity, by using the cancellation token source object from which we have taken the cancellation token.

因为取消令牌源实现了 IDisposable ,所以我们应该尽可能地调用它的 Dispose 方法.这个问题的重点是确定何时使用给定的取消令牌来源.

Because cancellation token source implements IDisposable, we should call its Dispose method as far as we are done with it. The point of this question is determining exactly when you are done with a given cancellation token source.

让我们假设您决定通过在取消令牌源上调用 Cancel 方法来取消正在进行的工作:是否有必要在调用处置 ?

Let's suppose that you decide to cancel the ongoing work by calling the Cancel method on the cancellation token source: is it necessary to wait for the completion of the ongoing operation before calling Dispose ?

换句话说,我应该这样做吗:

Put in other words, should I do this way:

class Program 
{
  static void Main(string[] args) 
  {
    var cts = new CancellationTokenSource();
    var token = cts.Token;

    DoSomeAsyncWork(token); // starts the asynchronous work in a fire and forget manner

    // do some other stuff here 

    cts.Cancel();
    cts.Dispose(); // I call Dispose immediately after cancelling without waiting for the completion of ongoing work listening to the cancellation requests via the token

    // do some other stuff here not involving the cancellation token source because it's disposed
  }

  async static Task DoSomeAsyncWork(CancellationToken token) 
  {
     await Task.Delay(5000, token).ConfigureAwait(false);
  }
}

或这种方式:

class Program 
{
  static async Task Main(string[] args) 
  {
    var cts = new CancellationTokenSource();
    var token = cts.Token;

    var task = DoSomeAsyncWork(token); // starts the asynchronous work in a fire and forget manner

    // do some other stuff here 

    cts.Cancel();

    try 
    {
      await task.ConfigureAwait(false);
    }
    catch(OperationCanceledException) 
    {
      // this exception is raised by design by the cancellation
    }
    catch (Exception) 
    {
      // an error has occurred in the asynchronous work before cancellation was requested
    }

    cts.Dispose(); // I call Dispose only when I'm sure that the ongoing work has completed

    // do some other stuff here not involving the cancellation token source because it's disposed
  }

  async static Task DoSomeAsyncWork(CancellationToken token) 
  {
     await Task.Delay(5000, token).ConfigureAwait(false);
  }
}

其他详细信息:我所指的代码是在ASP.NET core 2.2 Web应用程序内部编写的,这里我使用控制台应用程序来简化我的示例.

Additional details: the code I'm referring to is written inside an ASP.NET core 2.2 web application, here I'm using a console application scenario just to simplify my example.

我在stackoverflow上发现了类似的问题,询问是否需要处理取消令牌源对象.一些答案表明,在某些情况下,确实不需要处置此对象.

I've found similar questions on stackoverflow asking for the need to dispose of cancellation token sources objects. Some of the answers suggest that in some scenario disposing of this object is not really needed.

我处理整个 IDisposable 主题的方法是,我总是倾向于遵守类的公开合同,换句话说,如果对象声称是可抛弃的,我宁愿总是调用完成后处理.我不喜欢通过依赖类的实现细节来猜测是否真的需要调用dispose的想法,而该实现细节可能会在将来的发行版中以无证方式改变.

My approach to the whole IDisposable subject is that I always tend to adhere to the exposed contract of a class, put another way if an object claims to be disposable I prefer to always call Dispose when I'm done with it. I don't like the idea of guessing whether or not calling dispose is really required by depending on implementation details of the class that could change in a future release in an undocumented manner.

推荐答案

正确的做法是 second -在确定任务已取消后,您处置 CancellationTokenSource . CancellationToken 依赖于 CancellationTokenSource 中的信息才能正常运行.尽管当前的实现 CancellationToken 的编写方式可以解决,即使处理从其创建的CTS时也不会抛出异常,但它可能无法正常运行或始终如预期那样运行.

The correct practice is second - you dispose of the CancellationTokenSource after you are sure the task is cancelled. CancellationToken relies on information from CancellationTokenSource to function properly. While the current implementation CancellationToken is written in such a way that is will still work even without throwing exceptions if the CTS it was created from is disposed, it may not behave properly or always as expected.

这篇关于正确的模式以处理取消令牌源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆