Calling Thread.Abort on a thread from a ThreadPool

独自空忆成欢 提交于 2019-11-29 09:11:47

No, you shouldn't call Abort on threads in the thread pool. From my local testing, it seems that the ThreadPool does recreate threads if you abort them - I aborted 1000 thread pool threads and it was still working. I don't know if you should rely on this behaviour, but maybe you can get away with it in this case. In general though using Thread.Abort is not the right way to do this.

The correct way to call a function you don't trust to behave well is to start it in a new process and kill the process if necessary.

The use of Thread.Abort is not adviced, because it can leave your application in an invalid state. The reason for this is that when demanding a thread to abort, an exception can be raised in almost any possible place in that 3rd party library. It's possible that there are code segments that aren't written to be able to cope with these asynchronous aborts.

So while it is generally not advised to abort threads, there are hosts that are very aggressive in aborting threads. One of them is ASP.NET. When a request takes too long, it will abort the thread for you. So with this in mind it's silly to say "never abort threads".

I advice you to find out where this code hangs (the stack trace of ThreadAbortException should give you a lot of information). If it always hangs on the same place (it's probably a deadlock), find out with Reflector if aborting a thread at that point will result in some state corruption. With that information you can perhaps already fix the problem (perhaps you lock on a object of that library) or can send a mail to the writer of that library. If this all doesn't help and you see there is not a risk in aborting it, be pragmatic and kill it :-)

However, if there is a change of any state corruption, you should try to go with Mark Byers' answer. That is: try running that library in its own AppDomain. This way you can unload the complete AppDomain and there is no change in it affecting your application.

To clarify what Mark is saying, if you call Thread.Abort you have no idea where it will abort in the 3rd party component due to the special nature of the ThreadAbortException - it could leave a FileStream open for example.

I would personally create the Threads myself, referenced in a IList or Queue (as the ThreadPool is better suited for fire and forgets or WaitHandles), and depending on if you think aborting a thread that is using the 3rd party component isn't that dangerous, Abort it.

If you think aborting may leave the 3rd party library in an unacceptable state, Join the threads that haven't completed one by one, after a set amount of time using a System.Threading.Timer

Alternatively

To stick with using ThreadPool, you could use this Smart Thread Pool instead.

Read 'Abortable Thread Pool' by Stephen Toub. He provides source code for an abortable thread pool. Its an interesting read.

He calls his own callback 'HandleItem' when queueing the threadpool. Inside 'HandleItem' he then executes the actual callback, after adding the current thread to a dictionary list inside his wrapper class.

ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem));

HandleItem(...) {
...
_threads.Add(item, Thread.CurrentThread);
...
}

He uses a Dictionary to Link his WorkItems to Threads, when a user wants to cancel a thread it does a look up and cancels that particular thread.

Dictionary<WorkItem, Thread>() _threads = New Dictionary<WorkItem, Thread>();

http://msdn.microsoft.com/en-us/magazine/cc163644.aspx

You have another option (which I would take if I had a free day in front of me):

reverse-engineer the third-party component using reflector and actually fix the blocking call to make it asynchroneous.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!