多次调用CancellationTokenSource.Cancel是否安全?

时间:2018-10-15 21:22:15

标签: c# cancellationtokensource

例如,如果我想取消某个Dispose()调用(can be called multiple times)中的某些操作,那么我是否需要写

public void Dispose()
{
    if (!cancellationTokenSource.IsCancellationRequested)
    {
        cancellationTokenSource.Cancel();
    }
}

还是更简单

public void Dispose()
{
    cancellationTokenSource.Cancel();
}

(欢迎您评论在Dispose方法中取消操作是否明智,但这不是此问题的重点。)

2 个答案:

答案 0 :(得分:2)

是的

但前提是尚未处置CancellationTokenSource

来自reference source

ThrowIfDisposed();

// ...

// fast-path test to check if Notify has been called previously
if (IsCancellationRequested)
    return;

答案 1 :(得分:0)

这似乎是关于Dispose模式的一个问题,然后是关于CancellationToken或其他任何问题。我不确定您是否正确实施了上述模式。这是母校的官方MS文档: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern

这是我的解释:

有两个处置级别:处置和终结。由于两者的代码非常相似,因此通常将它们组合为一个函数(在C#中通常为Dispose)。主要区别在于是否将其中继到包含的类。您总是中继一个Dispose调用(中继通常是Dispose所涉及的)。您永远不会中继Finalization调用(Finalization仅在该实例与GC之间)。

还有两种情况:一种是直接处理非托管资源。其中只有一个可以处理另一个Disposeable类。

直接更改资源

在这种情况下,您要做的第一件事是实现终结器,因此至少GC可以可靠地清除它。然后,您将IDisposeable实现为附加功能,以便程序员可以使用诸如using模式之类的东西来在运行时清除确定性内容。

处理实现IDisposeable的东西

您拥有实现IDisposeable的资源(例如文件流引用)。您在类中实现IDisposeable的唯一目的是将Dispose()调用中继到所述FileStream。这是更常见的情况。大概占所有Dispose实现的95-99%。

这里要记住的一件事是“ Dispose”和“ Finalize”通常意味着较低级别的清除。调用dispose的SQLConenction将首先关闭(如果需要)。您处理掉的文件句柄也将首先关闭。即使调用cancellationTokenSource.Cancel不可重复,cancellationTokenSource.Dispose也应在操作中调用Cancel并应可重复。该类本身确实实现了IDisposeable。而且,如果有任何类,通常只调用Dispose而不是通过Cancel手动进行清理通常是节省的:https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=netframework-4.7.2