.NET 中的线程中止

Posted

技术标签:

【中文标题】.NET 中的线程中止【英文标题】:Thread Abort in .NET 【发布时间】:2010-02-01 20:57:23 【问题描述】:

我有一个线程正在分析文件并对数据库进行事务调用,每个事务都有一个审计条目作为其事务的一部分。调用 Thread.Abort() 来停止文件的处理有什么大问题吗?而不是到处散布丑陋的安全点?

文件将在 Abort 调用后关闭。

【问题讨论】:

【参考方案1】:

明显的问题是放弃事务的风险,这可能会导致阻塞一段不确定的时间(或直到超时)。但是你可以让所有分类变得一团糟——不可恢复的Monitor锁、信号量等、内存泄漏等。

简而言之:尽量避免中止线程,除非您确切地知道它当时正在做什么。你可以知道它在做什么的唯一方法是它是否已经在一个已知的“安全点”(用你的术语)——所以你不妨抛出一个异常或其他东西,让它以一种有管理的方式自我提升.

【讨论】:

事务正在运行的会话将被关闭,线程正在运行的类将被释放。这意味着服务器将回滚事务,并且可以从取消功能正确关闭该类。哪些锁、信号量等会丢失? @Will:执行清理时可能会发生中止。这可能意味着您的清理不会完成。此外,Abort 可能会破坏 lock 语句(有一些保护措施,但不能保证不会)。所以你最终可能会得到一个不会再次解锁的锁。 @Ruben:线程中止不会中断清理逻辑:“如果您在受限执行区域 (CER)、finally 块、catch 块、.cctor 内执行,我们不会处理线程中止, “乔·达菲。 @Sergey:不幸的是,这些并不是唯一可以进行清理的地方。例如,lock(x) 看起来像 Monitor.Enter(x) try ... finally Monitor.Exit(x); ,这意味着在 Enter 和 try 之间可能会发生 Abort。此外,不能保证清理代码在 finally 等内部,它也可以是不期望抛出异常的代码(因为它似乎是异常安全的,如果忽略异步异常,或者它是设置代码设置清理代码要使用的标志)。中止使所有这些事情变得非常复杂。 @Ruben:我完全同意,处理异步异常非常危险且容易出错。【参考方案2】:

最佳实践:仅在您终止进程时中止线程。

【讨论】:

【参考方案3】:

尝试 Thread.Interrupt() 强制线程退出等待状态。

MSDN page

【讨论】:

以上是关于.NET 中的线程中止的主要内容,如果未能解决你的问题,请参考以下文章

由于线程退出或 WCF 中的应用程序请求,I/O 操作已中止

std::thread,在线程中抛出异常会导致 Visual C++ 中的中止错误

在 .NET 中中止线程时,这段代码会损坏吗?

上传文件处理数据的时候提示 正在中止线程

.net的 async 和 await

中止线程