问题Thread.Abort
是你ThreadAbortException
可以在任何两个指令之间抛出(几乎)。
如果您采用一些非常简单的代码,例如:
public void M()
{
using (CreateThing())
{
}
}
public IDisposable CreateThing() => null;
并查看生成的 C# 和 IL:
public void M()
{
IDisposable disposable = CreateThing();
try
{
}
finally
{
if (disposable != null)
{
disposable.Dispose();
}
}
}
CreateThing
您可以看到在被调用和进入try
块之间有几个指令。有一个很小的机会窗口,如果Thread.Abort
当时被调用,您的对象将不会被释放。
所以使用IDisposable
并using
不能保证你的资源在面对Thread.Abort
.
Thread.Abort
从 .NET Standard 中删除以及为什么应该使用它是有充分理由的CancellationToken
。
您应该使用CancellationToken
,并且您的代码应该检查它是否CancellationToken.ThrowIfCancellationRequested()
在合适的安全点被取消(使用)。
顺便说一句,lock
语句使用了一个重载,Monitor.Enter
它返回一个布尔值,表示锁是否被实际获取,并且:
lock (lockObject)
{
}
编译为:
bool lockTaken = false;
try
{
Monitor.Enter(lockObject, ref lockTaken);
}
finally
{
if (lockTaken)
Monitor.Exit(lockObject);
}
为了避免这个问题。
但是,当使用任何其他同步方法时,您不会得到这种奢侈 - 仅lock
- 因此您很容易死锁。