I understand that calling Thread.Abort() is BAD AND WRONG because of various reasons
- Can be locking or in other critical region
- Could be midway through an I/O operation, resource won’t get cleaned up
- Code can swallow ThreadAbortException
- Could be midway through a state change operation, and leave the program in an invalid state.
Assuming that the thread’s Run() method:
- Does not use concurrency primitives.
- Does not perform any I/O.
- Does not swallow such exceptions.
- Is exposed to a read-only API, so cannot change program state.
Question:
If I were to call Abort() on such a thread, is the damage done (with regards to corruption) localized? As in, can I rely on my program, sans the recently aborted thread, to continue to behave normally, or is my entire process/AppDomain/?? then potentially corrupted?
If I remove assumptions 1 and 2 would abort() corruption be localized to the specific concurrency primitives and i/o resources it accessed? Or can it propogate outwards?
Why am I flogging the Thread.Abort() dead horse:
I’m writing a thick client c# winforms application. One feature s the ability for the user to write code in c# which implements interfaces on my domain objects which can then be plugged into my application (code is compiled into an assembly via codedom and loaded using reflection);
So the idea is the user could then write
public class CustomComputation : IComputationThing
{
public void Compute(object context)
{
while (true) ;
}
}
and I could then reflect on the generated assembly, extract and instantiate an instance of CustomComputation, and call Compute(...); Pretty straightforward stuff.
The problem is that the user could then write, well, the above – an infinite loop, or some other exponential time computation he decides he doesn’t want to wait for.
I am trying to investigate my options for providing a best-effort recovery for when users write some infinite-looping (or exponential time etc) code and wants to abort from that. While I do intend to ask users to adhere to a cancellation pattern but ultimately there is no guarantee that they will.
As mentioned by Vilx- you could consider putting the "user" code in another AppDomain.
In fact, since .Net 3.5, the .Net Framework has included the
System.AddInnamespace, which provides a simplified way of isolating "add-in" code in seperate app domains (amongst other things). Provided there isn’t too much cross-domain communication required, this gives you a nice level of isolation whereby the worst case scenario is that you tear down an AppDomain that is specific to the user code.See this MSDN article and the CLR-Addin team’s blog for more information.
Additionally, although it doesn’t solve everything, you could start by firing a Thread.Interrupt. This will cause a ThreadInterruptException to be raised in a similar way to ThreadAbortException, except that it will occur oinly at defined points in the code; when the thread blocks or sleeps, rather than absolutely anywhere. It probably won’t help in the tight-loop example you mention above, but would if the loop had a Thread.Sleep(0).
You can always graduate your options: