4

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.)

Ozzah
  • 10,631
  • 16
  • 77
  • 116
  • Killing a thread is not a good idea as it doesn't release resources. I'd suggest using some maintained component for .NET which doesn't have such bugs and where you can get support. – Eugene Mayevski 'Callback Apr 06 '11 at 04:48
  • Also, in general, don't start your own threads. http://stackoverflow.com/questions/684640/advantage-of-using-thread-start-vs-queueuserworkitem – Cheeso Apr 09 '11 at 09:10

7 Answers7

9

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.

Bradley Smith
  • 13,353
  • 4
  • 44
  • 57
5

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.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

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();
}
slow
  • 566
  • 4
  • 17
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • I didn't think it would be so simple. I'm going to give this a try now. I thought Thread.Abort() just sent a signal to the thread to abort, which would trigger an event handler in the Thread. – Ozzah Apr 06 '11 at 02:38
  • 1
    @Ozzah: No; that's the safe way to do it. `Abort` is _dangerous_. – SLaks Apr 06 '11 at 02:38
  • @SLaks although [MSDN](http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx) says `Calling this method **usually** terminates the thread.` I wonder what that implies. – Bala R Apr 06 '11 at 02:40
  • 1
    If the thread calls `ResetAbort` in a `catch` or `finally`, it won't terminate. – SLaks Apr 06 '11 at 02:44
2

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.

Cheeso
  • 189,189
  • 101
  • 473
  • 713
1

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

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
0

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

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
0

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

Andrew Cooper
  • 32,176
  • 5
  • 81
  • 116