如何在C#中终止一个线程?

19

我想尝试使用C#进行线程编程,我对C中的线程有一些了解。

所以我想问一下如果我想终止一个线程,我应该使用smt.Abort()还是让它在函数结束后自动"kill itself"?

此外,在C#中是否有像C中的pthread_exit()这样的东西?


通常最好让线程“自行结束执行方法”,这样它才能被终止。 - user166390
1
你使用的是哪个版本的.NET? - techBeginner
终止线程很麻烦,但自杀通常不是。就像pthread_exit()一样。Thread.CurrentThread.Abort()并不是那么有用。 - Hans Passant
可能是在.NET中清除终止线程的问题的重复。 - Brian Gideon
4个回答

77
Thread.Abort方法会"强制终止"线程,但这相当于:

场景:您想关闭计算机。

解决方案:您在计算机上绑上炸药,点燃它,然后跑开。

更好的方法是通过触发“退出条件”来结束线程,例如使用CancellationTokenSource.Cancel、设置某个(安全访问的)“正在运行”布尔值等,并调用Thread.Join方法。这就像:

场景:您想关闭计算机。

解决方案:您单击开始按钮、选择关闭并等待计算机关机。


11
你如何将 CancellationTokenSource 传递给 System.Threading.Thread 对象? - AaA
18
那个炸药的比喻 :P. +1 - RBT
@AaA:将其作为参数传递。 - Visual Vincent
4
也许提供一些代码会有助于改进这个答案? - Adam B

11

一旦函数结束,您无需手动终止线程。

如果您启动一个线程来运行方法,则一旦该方法返回,线程将自动关闭,因为它没有其他要执行的内容。*

当然,您可以通过调用Abort()手动中止线程,但这几乎不被推荐,因为可能会导致线程状态损坏,由于不可靠地确定线程在其当前执行状态中的位置。如果您需要处理线程的停止,可以考虑使用CancellationToken。您还可以阅读MSDN上的取消托管线程文章。

** 除非您正在使用线程池执行您的工作。您不必担心中止这些线程,因为它们在不同的排队任务之间重复使用。


你如何终止一个无限期监听端口的套接字监听器线程?顺便说一句,我认为Thread类不接受CancellationToken,是吗? - AaA
@AaA请查看我的回答中的第二个引用链接,它为您提供了一个CancellationToken示例。 - Rudi Visser
你能在 System.Threading.Thread 类中使用 CancellationToken 吗?它不会像静态布尔变量一样行为吗? - AaA
1
@AaA 再次参考“取消托管线程”主题讨论。它将按照您编写的方式进行操作。 - Rudi Visser

4
从外部(线程之外)终止线程是一个不好的主意;当您异步杀死它时,您永远不知道线程正在做什么。在C#中,如果您的线程函数返回,线程就会结束。
这篇MSDN文章 如何创建和终止线程 (C#编程指南) 有一些注意事项和一些示例代码,您可能会发现有用。

你提出的建议很酷也很可行,但是你如何让一个线程“闭嘴,现在轮到我说话了”? - AaA
2
不确定您具体的意思是什么,但大多数编写线程代码的人都会给运行在线程内部的循环一个外部信号,以便线程的循环可以检查并以有序的方式关闭。如果您有特定的情景,请发布一个带有详细信息的问题。 - MikeB
你说得完全正确。我也是这样做的,但有时(例如)一个监听套接字会陷入读取循环中,不想退出循环并听取您的退出指令,在这种情况下,Thread.Abort() 是解决问题的最后手段。你可能会丢失一些数据,但至少你拯救了你的程序免于崩溃。 - AaA

-1
Thread.Abort()
Thread.Join();
Thread = null;

“Join” 不会终止线程,它会等待线程完成,如果需要等待多个线程完成(例如 t1.Join(); t2.Join();),则使用它 - 通常安排/运行线程的代码会使用这个方法。 - Matt
Thread.Abort()现已被弃用,不再起作用,曾经用于强制终止线程,无论它正在执行什么操作以及它仍然打开了哪些资源等。此外,代码的其余部分并不能终止一个线程。 - BasementScience

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