C# How to kill a blocked thread?

2019-07-18 13:01发布

问题:

I have a thread:

void threadCode(object o)
{
  doStuffHere(o); // Blocking call. Sometimes hangs.
}

and I'm calling it like this:

Thread t = new Thread(new ThreadStart(delegate()
  {
    threadCode(o);
  }));
t.Start();

StopWatch sw = new StopWatch();
sw.Start();

while (t.IsAlive)
{
  Application.DoEvents();

  if (sw.EllapsedMilliseconds > myTimeout)
    // Somehow kill t even though doStuffHere(o) is blocked (but hung)
}

I'm using the .NET Zip Library and calling ZipFile.CommitUpdate() which works most of the time, but sometimes just hangs. I don't know why, I can't see anything in the documentation which specifies why this is happening. A small file which should take no longer than 5 - 10 seconds will sometimes sit there for more then 5 minutes with no progress. I/O graphs in process explorer show that the process is not reading or writing, and there is no CPU usage. Basically, if this happens, I want to kill CommitUpdate() and try again once or twice before giving up.

Any idea how I can kill a thread stuck in a blocking call?

(Alternatively - those of you with experience with this zip library: do you know why it might be hanging with some files sometimes? I'm modifying the contents of .docx and .pptx (GZip) files. This would be an ideal solution.)

回答1:

You can call Thread.Abort to bloodily murder the thread.

The thread will not be able to clean up after itself (except for finally blocks); depending on exactly what it was doing at the time, it could seriously mess up your program.



回答2:

If you're going to terminate the hanging thread by using Thread.Abort(), make sure you handle ThreadAbortException in your thread code. The normal pattern is:

try {
    // do work here
}
catch (ThreadAbortException) {
    // allows your thread to gracefully terminate
    Thread.ResetAbort();
}
catch {
    // regular exception handling
}

If you don't follow the above pattern, then at best your threads will terminate ungracefully. At worst, you could run into a number of other problems.



回答3:

DO NOT use Thread.Abort() to workaround a bug in a library you're using. (Or it could be a bug in your code).

Either get the original bug fixed, or move to a different library.

ps: You might want to try DotNetZip, in lieu of SharpZipLib.



回答4:

Alternative to using a Stopwatch, you could do this:

Thread thread = new Thread(new ThreadStart(delegate()
{
   threadCode(o);
}));
thread.Start();

thread.Join(myTimeout);
if(thread.IsAlive)
{
   thread.Abort();
}


回答5:

Use the Thread.Abort() method to kill a thread. See http://msdn.microsoft.com/en-us/library/aa332365(VS.71).aspx for more details.



回答6:

As a last resort you could use Thread.Abort() to terminate the thread - don't expect any orderly shutdown.



回答7:

I haven't done this myself, so I not sure about this, but does t.Abort(); do the trick?