What can cause issues when thread is aborted?
I need to use Thread.Abort()
in my code because the thread runs complex code that have a lot of loops, objects and conditions.
I know that Thread.Abort()
can lead to deadlock when using Monitor
, also it can prevent resources from being released, but I can handle these problems.
I use IDisposable
/ using
pattern or catch ThreadAbortException
to guarantee that all resources are released and asynchronous operations are stopped.
The application seems to works fine now. But, since the code is pretty complex, I'm not sure if there could be some rare cases when aborting the thread can lead to memory leaks or unhandled exceptions.
Is there any .net classes (eg FileStream
, Dictionary
) that can cause problems if thread is aborted when their code are executed? Or some other issues that I should be aware of?
The problem with Thread.Abort
is that your ThreadAbortException
can be thrown between any two instructions (almost).
If you take some very simple code like:
public void M()
{
using (CreateThing())
{
}
}
public IDisposable CreateThing() => null;
And look at the generated C# and IL :
public void M()
{
IDisposable disposable = CreateThing();
try
{
}
finally
{
if (disposable != null)
{
disposable.Dispose();
}
}
}
You can see that there's a couple of instructions between CreateThing
being called, and it entering the try
block. There's a small window of opportunity where, if Thread.Abort
is called right then, your object will not be disposed.
So using IDisposable
and using
does not guarantee that your resources get freed in the face of Thread.Abort
.
There is a very good reason why Thread.Abort
was removed from .NET Standard, and why you should use CancellationToken
instead.
You should use CancellationToken
, and your code should check whether it's been cancelled (using CancellationToken.ThrowIfCancellationRequested()
) at suitable, safe points.
As an aside, lock
statements use an overload of Monitor.Enter
which returns a boolean saying whether the lock was actually acquired, and:
lock (lockObject)
{
}
compiles to:
bool lockTaken = false;
try
{
Monitor.Enter(lockObject, ref lockTaken);
}
finally
{
if (lockTaken)
Monitor.Exit(lockObject);
}
to avoid exactly this problem.
However, you don't get this luxury when using any other synchronization methods - only lock
- and so you can easily deadlock.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.