gpt4 book ai didi

c# - 在 try{} 中设置字段值并在 finally{} 中调用基类

转载 作者:太空狗 更新时间:2023-10-30 01:16:55 25 4
gpt4 key购买 nike

我在浏览 .NET Framework 源代码试图理解另一个问题时看到了这段代码(在 PeerNearMe.cs 中来自 System.Net.PeerToPeer.Collaboration):

private bool m_Disposed; 

protected override void Dispose(bool disposing)
{
if (!m_Disposed){
try{
m_Disposed = true;
}
finally{
base.Dispose(disposing);
}
}
}

有没有理由把变量赋值放在try中?堵塞?它可能以任何方式失败,但有异常(exception)吗?!起初我认为这是因为即使线程被 Thread.Abort() 中止,finally 也会被执行。 :

Unexecuted finally blocks are executed before the thread is aborted.

在这种情况下我期望 try block 包含所有方法体:

try {
if (!m_disposed)
m_disposed = true;
}
finally {
base.Dispose(disposing)
}

但是they还说:

The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region. If the thread that calls Abort holds a lock that the aborted thread requires, a deadlock can occur.

在这种情况下,IMO 调用基类虚方法有点在黑暗中跳跃

简而言之:该代码的意义何在?它真正试图实现什么?如果是因为Thread.Abort()那不就是吗?

编辑:如果真的只是因为 Thread.Abort()那么如果在 if (!m_Disposed) { 之后发生中止,它就不会完成它的工作。但在 try { 之前.注意 Dispose()必须对多次调用具有弹性并且什么也不做(无论何时调用)。

最佳答案

唯一可能发生的是异步异常 - Thread.Abort 是一个例子,但也有 Thread.InterruptOutOfMemoryException.

您的建议实际上破坏了代码,因为您调用了 base.Dispose 而不管该实例是否已被处置 - 这不是本意。

现在,Thread.Abort 应该只在终止应用程序域时使用 - 所以您不关心 m_disposed = true 是否成功,域是无论如何很快就会被拆除。但是,您仍然关心释放任何 native 资源,因为它们通常与进程相关,而不是应用程序域(有时,它们甚至超越进程或整个机器)。

finally 中的代码即使在 Thread.Abort 中也有机会运行 - 没有其他方法可以确保代码在异步异常期间运行。通过在 finally 子句中调用 base.Dispose,您可以确保它至少有机会执行,并且不会在操作中途终止(尽管请注意,所有执行的 finally 子句都有固定的时间限制 - 您不想在 finally 中做任何复杂的事情。

现在,在这种特殊情况下,没有真正的理由这样做——基类也不做任何事情。所以它可能只是团队使用的一个常见的 Dispose 模式 :) 因为 Dispose 是为 native 资源的确定性释放而设计的,所以在 finally 中调用它是非常安全的 子句 - 它不应该做任何工作,只是释放 native 资源。当然,Dispose 经常被滥用 - 但你只会收获你所播种的种子。

最后,不要忘记这也正是 using 子句的作用,所以如果您正在使用 using,那么您已经在运行 Dispose 方法在 finally 子句中!

using (var bmp = new Bitmap())
{
...
}

翻译成等同于

Bitmap bmp = null;
try
{
bmp = new Bitmap();

...
}
finally
{
if (bmp != null) bmp.Dispose();
}

总而言之,这个实现没有任何可疑之处,真的:)

关于c# - 在 try{} 中设置字段值并在 finally{} 中调用基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33518185/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com