【发布时间】:2011-10-03 12:10:50
【问题描述】:
假设我有这个代码:
static void Main(string[] args)
{
var thread = new Thread(() =>
{
try
{
throw new InvalidOperationException();
}
catch (Exception)
{
Thread.Sleep(Timeout.Infinite);
}
});
thread.Start();
Thread.Sleep(TimeSpan.FromSeconds(1));
thread.Abort();
thread.Join();
}
它启动线程,然后线程在 catch 块中进入睡眠状态,之后我们尝试中止线程。
Abort 方法必须引发 ThreadAbortException。但是在 catch 块中它不会发生。 我是documented:
如果正在调用 Abort 的线程可能会阻塞 aborted 位于代码的受保护区域中,例如 catch 块, finally 块,或受约束的执行区域。如果那个线程 调用 Abort 持有中止线程所需的锁,即死锁 可能发生。
我的问题是为什么。为什么它会这样工作?因为在 catch 块中,我们可以引发任何异常并且所有工作都必须这样做。
更新: 来自 Jordão 的 link。接受,因为这是最容易理解的说明。
受约束的执行区域 .NET Framework 2.0 引入了 受约束的执行区域 (CER),对 运行时和开发人员。在标记为 CER 的代码区域中, 运行时受限于抛出某些异步 会阻止该区域在其 整体。开发人员也受限于可以采取的行动 在该地区进行。这创建了一个框架和一个执行 编写可靠托管代码的机制,使其成为关键参与者 在 .NET Framework 2.0 的可靠性故事中。对于运行时 为了减轻负担,它为 CER 提供了两种便利。首先, 运行时将延迟在 CER 中执行的代码的线程中止。 换句话说,如果一个线程调用 Thread.Abort 来中止另一个线程 当前正在 CER 中执行的,运行时将不会中止 目标线程直到执行离开 CER。二、 运行时将尽快准备 CER,以避免 内存不足的情况。这意味着运行时会做 它通常会在代码区域期间执行的所有操作 JIT 编译。它还将探测一定数量的空闲堆栈 帮助消除堆栈溢出异常的空间。通过做这项工作 预先,运行时可以更好地避免可能发生的异常 区域内,防止资源被清理 适当地。为了有效地使用 CER,开发人员应避免 某些可能导致异步异常的操作。编码 受限于执行某些操作,包括诸如 显式分配、装箱、虚拟方法调用(除非目标 的虚方法调用已经准备好了),方法调用 通过反射,使用 Monitor.Enter(或 C# 中的 lock 关键字 和 Visual Basic® 中的 SyncLock)、isinst 和 castclass 指令 COM 对象,通过透明代理访问字段,序列化, 和多维数组访问。简而言之,CER 是一种移动方式 从您的代码到某个时间的任何运行时引发的故障点 在代码运行之前(在 JIT 编译的情况下),或者在代码之后 完成(用于线程中止)。然而,CERs 确实限制了 你可以写的代码。诸如不允许大多数分配的限制 或对未准备目标的虚拟方法调用很重要, 这意味着创作它们的开发成本很高。这意味着 CER 不适合大量通用代码,而且它们 相反,应该将其视为一种保证执行的技术 小代码区域。
【问题讨论】:
-
这对我来说似乎是一个错误,Abort() 只是被忽略了。将此发布到 connect.microsoft.com
标签: c# multithreading try-catch