在 Delphi 中释放 TCriticalSection 对象的正确方法

Correct way to free TCriticalSection object in Delphi

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

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

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

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

由于多种原因,这不是释放临界区的正确方法。

根据文档EnterCriticalSection function

This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait operation on the critical section times out. The timeout interval is specified by the following registry value: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout. Do not handle a possible deadlock exception; instead, debug the application.

If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.

While a process is exiting, if a call to EnterCriticalSection would block, it will instead terminate the process immediately. This may cause global destructors to not be called.

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

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

但是在任何平台上释放关键部分实例之前不应调用 Acquire 的最值得注意的原因是,如果此时有一些其他线程正在做一些工作并且依赖于该关键部分部分表示您的关机和清洁过程完全中断。换句话说,如果 Acquire 解决了你的问题,真正的问题在另一座城堡里,你并没有真正解决任何问题,你只是稍微改变了动态,这可能有效也可能无效,这取决于所有其他代码涉及。

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

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