multithreading - 在 Delphi 中释放 TCriticalSection 对象的正确方法
问题描述
这是释放TCriticalSection
在 Delphi 的初始化部分中创建的对象的正确方法吗?
initialization
FPoolingCS := TCriticalSection.Create;
finalization
FPoolingCS.Acquire;
FreeAndNil(FPoolingCS);
我应该在 之前调用该Release
方法Free
吗?
该Acquire
方法会抛出一些我需要处理的异常吗?
解决方案
由于几个原因,这不是释放关键部分的正确方法。
如果对关键部分的等待操作超时,此函数可以引发 EXCEPTION_POSSIBLE_DEADLOCK。超时间隔由以下注册表值指定:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout。不处理可能的死锁异常;相反,调试应用程序。
如果一个临界区在它仍然拥有的时候被删除,那么等待被删除临界区所有权的线程的状态是未定义的。
当进程退出时,如果对 EnterCriticalSection 的调用会阻塞,它将立即终止进程。这可能会导致不调用全局析构函数。
FPoolingCS.Acquire
在 Windows 平台调用函数EnterCriticalSection
。所以第一个问题,获取临界区是否会引发异常,答案是肯定的。
同样根据文档,您不应该尝试处理此类异常,但您必须调试应用程序,因为问题的根源在于其他一些代码。
但是,在任何平台上释放临界区实例之前不应调用的最显着原因Acquire
是,如果此时有一些其他线程正在做一些工作并且依赖于该临界区,则意味着您的关闭和清理过程完全被破坏. 换句话说,如果Acquire
解决了您的问题,真正的问题在另一座城堡中,而您还没有真正解决任何问题,您只是稍微改变了动态,这可能有效也可能无效,具体取决于所涉及的所有其他代码。
Release
出于同样的原因,之前调用Free
将毫无意义。如果还有其他涉及的线程仍在运行,它们可能会在Free
执行之前获取锁。
只需调用Free
关键部分,或者如果你喜欢使用FreeAndNil
它,如果你的关闭过程被破坏,它最终会崩溃。请记住,线程问题并不能始终如一地重现,因此没有崩溃仍然不意味着您拥有完全没有错误的代码。
推荐阅读
- java - 使用有限数量的连接和 Camel SFTP 传输文件
- python - Python 通过 txt 文件存储和访问信息
- python - 在标记推文时忽略“️”
- amazon-kinesis - zabbix模板中动态添加项目
- php - 如何使用 HTML 和 CSS 在 WordPress 中自定义帖子?
- javascript - 是否可以将数据从控制器获取到 cshtml?(JSON)
- javascript - 对象链式赋值如何在 javascript 中工作
- java - 自定义顶部和底部导航栏
- github - 我可以在 Github 上使用 https 调用访问 Private Repository RAW 文件吗?
- tvos - Superpowered可以用来输出5.1或7.1环绕声吗?