C#如何终止一个被阻塞的线程?

4

我有一个线程:

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

我这样调用它:

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

我正在使用.NET Zip Library,并调用ZipFile.CommitUpdate(),大多数情况下都有效,但有时会卡住。我不知道为什么,在文档中找不到任何指定原因的信息。一个小文件应该不需要超过5-10秒,但有时会停留5分钟以上而没有任何进展。在进程资源管理器中的I/O图表显示进程没有读取或写入,并且没有CPU使用率。基本上,如果发生这种情况,我想杀死CommitUpdate(),然后再试一两次,然后放弃。

有什么方法可以杀死被阻塞调用卡住的线程吗?

(或者-对于那些有使用此zip库经验的人:您知道为什么有时会挂起某些文件吗?我正在修改.docx和.pptx(GZip)文件的内容。这将是一个理想的解决方案。)


杀死线程并不是一个好主意,因为它不会释放资源。我建议使用一些维护良好的 .NET 组件,这些组件没有这样的 bug,并且您可以获得支持。 - Eugene Mayevski 'Callback
另外,一般情况下,请不要启动自己的线程。https://dev59.com/B3RB5IYBdhLWcg3wN1EQ - Cheeso
7个回答

9
如果您要使用Thread.Abort()终止挂起的线程,请确保在您的线程代码中处理 ThreadAbortException 。通常模式如下:
try {
    // do work here
}
catch (ThreadAbortException) {
    // allows your thread to gracefully terminate
    Thread.ResetAbort();
}
catch {
    // regular exception handling
}

如果您不按照上述模式进行操作,那么您的线程最好能够优雅地终止。最坏的情况下,您可能会遇到许多其他问题。

5
你可以调用Thread.Abort来强制终止线程。
线程将无法自我清理(除了finally块);根据它在执行时正在做什么,它可能会严重破坏你的程序。

2

除了使用Stopwatch,您还可以采用以下方式:

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

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

我没想到会这么简单。我现在要试一试。我原以为Thread.Abort()只是发送一个信号给线程来中止,然后会触发线程中的事件处理程序。 - Ozzah
1
@Ozzah:不,这是安全的做法。Abort是危险的。 - SLaks
@SLaks 尽管 MSDN 表示 调用此方法通常会终止线程。 我想知道这意味着什么。 - Bala R
1
如果线程在catchfinally中调用ResetAbort,它将不会终止。 - SLaks

2

不要使用Thread.Abort() 来解决你正在使用的库中的一个bug。(或者这可能是你代码中的一个bug)。

要么修复原始的bug,要么换用另一个库。

PS:你可能想尝试使用DotNetZip,而不是SharpZipLib。


1

0
作为最后的手段,您可以使用 Thread.Abort() 来终止线程 - 不要期望有任何有序的关闭。

0

我自己没有做过这个,所以不太确定,但是 t.Abort(); 可以解决问题吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接