C# 在ThreadAbortException上下文中,建议采用什么方法来防止资源泄漏?
我正在努力提高一段代码的异常安全性,我意识到,即使使用构造用C#C# 在ThreadAbortException上下文中,建议采用什么方法来防止资源泄漏?,c#,.net,idisposable,using,threadabortexception,C#,.net,Idisposable,Using,Threadabortexception,我正在努力提高一段代码的异常安全性,我意识到,即使使用构造用C#保护资源,引发的线程异常也可能导致不希望的资源泄漏。例如,考虑下面的代码(可以在一个单独的线程中运行)。 如果运行此代码的线程异常终止,那么我希望立即关闭filename引用的文件句柄。我是否可以在不使用try/finally块替换using构造的情况下执行此操作 我的假设是,ThreadAbortException随时都可能被提出,这意味着我应该注意语句之间发生的事情。虽然我可以使用try/finally块防止CreateWrit
保护资源,引发的线程异常
也可能导致不希望的资源泄漏。例如,考虑下面的代码(可以在一个单独的线程中运行)。
如果运行此代码的线程异常终止,那么我希望立即关闭filename
引用的文件句柄。我是否可以在不使用try/finally块替换using
构造的情况下执行此操作
我的假设是,ThreadAbortException
随时都可能被提出,这意味着我应该注意语句之间发生的事情。虽然我可以使用try/finally块防止CreateWriter
中的异常,但是using
构造在计算括号中的表达式之前不会执行相同的操作,这意味着如果异常在CreateWriter
返回后立即发生,则文件资源将保持打开状态
我知道终结器最终会释放文件句柄,但我想知道是否有一种确定性方法可以解决此问题,而不必在使用CreateWriter
的每个位置捕获ThreadAbortException
。是的,防止此问题的确定性方法是不使用Thread.Abort
。曾经向线程发出停止的信号,让它们优雅地终止Thread.Abort
是一个很大的麻烦,放在API中只是为了让你绊倒
线程中止最常用于发生致命错误的情况,因此您的响应可能是让应用程序终止。如果您试图干净地停止自己的线程,请使用Thread.Join()。这是一个折衷方案
确保立即关闭所有资源,即使存在ThreadAbortException
具有更简单的代码,但在调用Abort()时会临时泄漏资源
我想你不是在呼叫Abort,只是想在其他人呼叫时找到一种安全的方法。如果您正在呼叫Abort,那么我建议您不要。这不是你会遇到的唯一问题。还有其他的
#2是一个有效的选择,因为Abort()的调用者应该期望这样
如果你想选择#1,那么我认为即使是一次简单的尝试/捕获也不会有帮助。如果ThreadAbortException可以在任何地方发生,那么它仍然可以在文件打开后(在file.OpenWrite()内部)以及将其分配给可以调用Dispose()的变量之前发生——您将遇到与在代码中使用相同的问题
你需要像这样的语义学
using (var handle = GetUnOpenedHandle()) {
handle.Open(); // this can't involve assignment to any field of handle
}
我不确定这是否可行。在许多情况下(但肯定不是所有情况),您可以防止出现线程异常。NET BCL中的大多数关键代码都已经很好地实现了这一点。问题是很难做到正确。出于这个原因,大多数人建议避免线程中止,这是正确的。从2.0版开始,CLR使线程中止变得更容易容忍,并引入了一组新的API来帮助代码作者防范它们。深入了解所有这些是如何工作的
我相信您对使用
块的示例的关注是正确的。要使受约束的执行区域正常工作,带外(异步)异常必须在try
块中发生。但是,由于使用
展开的方式,表达式在try
块之外求值。将其与lock
块的扩展进行对比,后者从try
块中计算表达式。无论如何,这是真的,这是专门为了防止这些例外情况而改变的
所以问题是为什么使用
块时没有对进行相同的更改。这是一个可以接受的省略,因为假设线程中止之后总是会终止AppDomain,这无论如何都会触发终结器
所以是的。您的代码不能容忍带外(异步)异常。但是,比我聪明的人普遍认为不应该这样做。公平地说,MSDN也警告不要使用它。它是为了与backw兼容而维护的。
using (var handle = GetUnOpenedHandle()) {
handle.Open(); // this can't involve assignment to any field of handle
}