ExecuteCodeWithGuaranteedCleanup 何时真正保证清理?
我一直在阅读.NET 中的可靠性功能,并编写了以下内容类来探索 ExecuteCodeWithGuaranteedCleanup
class Failing
{
public void Fail()
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Code, Cleanup, "fail");
}
}
private void Code(object message)
{
// Some code in here that will cause an exception...
}
private void Cleanup(object message, bool something)
{
Console.WriteLine(message);
Console.ReadLine();
}
}
我已经尝试了 Code
方法的各种代码体。下面列出了这些及其运行时结果
导致 OutOfMemoryException
- Cleanup
不被调用
List<string> ss = new List<string>();
while (true)
{
string s = new string('x', 1000000);
ss.Add(s);
}
导致 StackOverflowException
- Cleanup
不被调用
Code(message); // recursive call
导致 ExecutionEngineException
- Cleanup
不被调用
Environment.FailFast(message.ToString());
导致ThreadAbortException
- Cleanup
does 被调用(但是常规的 try...finally
也可以捕获此异常)
Thread.CurrentThread.Abort();
所以问题是
- 我是否正确使用了 ExecuteCodeWithGuaranteedCleanup?
ExecuteCodeWithGuaranteedCleanup
什么时候真正有用?
I have been reading about Reliability Features in .NET and have written the following class to explore ExecuteCodeWithGuaranteedCleanup
class Failing
{
public void Fail()
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Code, Cleanup, "fail");
}
}
private void Code(object message)
{
// Some code in here that will cause an exception...
}
private void Cleanup(object message, bool something)
{
Console.WriteLine(message);
Console.ReadLine();
}
}
I have experimented with a variety of code bodies for the Code
method. These, and their runtime results are listed below
Causing an OutOfMemoryException
- Cleanup
does not get called
List<string> ss = new List<string>();
while (true)
{
string s = new string('x', 1000000);
ss.Add(s);
}
Causing a StackOverflowException
- Cleanup
does not get called
Code(message); // recursive call
Causing a ExecutionEngineException
- Cleanup
does not get called
Environment.FailFast(message.ToString());
Causing a ThreadAbortException
- Cleanup
does get called (however a regular try...finally
can also catch this exception)
Thread.CurrentThread.Abort();
So the questions are
- Am I using
ExecuteCodeWithGuaranteedCleanup
correctly? - When is
ExecuteCodeWithGuaranteedCleanup
actually useful?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有些异常对于进程来说是致命的,并且用户提供的代码的执行不会继续。
ExecuteCodeWithGuaranteedCleanup
方法的目的是让您可以将数据结构恢复到一致的状态。如果进程无论如何都会终止而无法阻止它,那么这就没有意义。当进程结束时,操作系统(假设它工作正常)将自动为您清理所有内核对象,无论进程结束的原因如何。正如 Hans 所暗示的那样,当代码在特定主机(尤其是 SQL Server)中运行时,主机的 ICLRPolicyManager 会发挥作用来确定哪些异常是致命的。请参阅本文档页面底部的漂亮网格:ICLRPolicyManager::SetActionOnFailure 方法
Some exceptions are fatal to the process and execution of user-supplied code just does not continue. The purpose of
ExecuteCodeWithGuaranteedCleanup
method is to so you can put your data structures back in a consistent state. If the process is going to die anyways with no way to stop it, this has no purpose. The OS (assuming it is working properly) will clean up any kernel objects automatically for you when a process ends, regardless of the reason the process ends.As Hans hints, the
ICLRPolicyManager
of the host comes into play to determine which exceptions are fatal in this way when code is run in a particular host (especially SQL Server). See the nice grid at the bottom of this documentation page: ICLRPolicyManager::SetActionOnFailure Method