繁体   English   中英

在 Delphi 中释放 TCriticalSection object 的正确方法

[英]Correct way to free TCriticalSection object in Delphi

这是释放在 Delphi 的初始化部分中创建的TCriticalSection object 的正确方法吗?

initialization
  FPoolingCS := TCriticalSection.Create;
finalization
  FPoolingCS.Acquire;
  FreeAndNil(FPoolingCS);

我应该在Free之前调用Release方法吗?

Acquire方法会抛出一些我需要处理的异常吗?

由于几个原因,这不是释放关键部分的正确方法。

根据文档EnterCriticalSection function

如果对临界区的等待操作超时,则此 function 可以引发 EXCEPTION_POSSIBLE_DEADLOCK。 超时间隔由以下注册表值指定:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout。 不处理可能的死锁异常; 相反,调试应用程序。

如果一个临界区在它仍然拥有的情况下被删除,则等待被删除临界区所有权的线程的 state 是未定义的。

当进程退出时,如果对 EnterCriticalSection 的调用会阻塞,它将立即终止进程。 这可能会导致不调用全局析构函数。

在 Windows 平台上调用FPoolingCS.Acquire调用EnterCriticalSection function。 所以第一个问题,获取临界区是否会引发异常,答案是肯定的。

同样根据文档,您不应该尝试处理此类异常,但您必须调试应用程序,因为问题的根源在于其他一些代码。

但是,在任何平台上发布临界区实例之前不应调用Acquire的最显着原因是,如果此时有一些其他线程正在做一些工作并依赖于该临界区,则意味着您的关闭和清理过程完全破碎的。 换句话说,如果Acquire解决了您的问题,真正的问题在另一座城堡中,而您还没有真正解决任何问题,您只是稍微改变了动态,这可能有效,也可能无效,具体取决于所涉及的所有其他代码。

出于同样的原因,在Free之前调用Release将毫无意义。 如果还有其他涉及的线程仍在运行,它们可能会在执行Free之前获取锁。

只需在关键部分调用Free ,或者如果您喜欢使用FreeAndNil ,如果您的关闭过程被破坏,它最终会崩溃。 请记住,线程问题并不能始终如一地重现,因此没有崩溃仍然不意味着您拥有完全没有错误的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM