例如,如果我想取消某个Dispose()
调用(can be called multiple times)中的某些操作,那么我是否需要写
public void Dispose()
{
if (!cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
}
}
还是更简单
public void Dispose()
{
cancellationTokenSource.Cancel();
}
(欢迎您评论在Dispose方法中取消操作是否明智,但这不是此问题的重点。)
答案 0 :(得分:2)
是的
但前提是尚未处置CancellationTokenSource
。
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