multithreading - 主线程 “blocked on critical section which is abandoned”

标签 multithreading delphi delphi-2010

我有一个使用OmniThreadLibrary的多线程应用程序。我滥用OTL来在辅助线程中打开ADO存储过程,除非有错误(大多数情况下甚至是错误的),否则它都可以工作。不幸的是,在这种情况下存在问题。

当我打开特定表单时,在线程“必须至少有一个字段”中将数据集复制到kb内存表中,该异常将由我处理并将消息发送到监视线程。该消息到达并成功存储在数据库中。当我关闭该窗体时,主VCL线程将挂起。

kbMemTable.LoadFromDataset(StoredProc, []); // throws

在调试器中暂停应用程序并查看线程列表,主要的VCL线程显示:
"Blocked on critical section which is abandoned owned by Process 0"

OTL线程仍处于 Activity 状态,并且线程池中的时间已满,因此似乎除主线程外其他所有东西都在工作。我还使用了DevExpress和Raise组件,它们有自己的线程,但没有命名(并且似乎不是问题的一部分),这意味着我有12个线程,其中只有5个是可识别的。

我强烈怀疑Delphi数据库中的某些内容已经捕获了该关键部分,然后由于异常而无法将其释放。我直接使用的Delphi/数据库源代码单元中似乎没有任何关键的部分,但是很显然那里有一个关键的部分。

这涉及太多的源代码以至于无法包含在内,而我的测试应用程序未显示该行为。

我正在寻求有关跟踪此问题的任何提示。

我目前的想法是切换到调试dcu并在我可以找到的每个关键部分创建时断点,然后看看会发生什么。我可以解决引发第一个异常的问题,但是我担心某些其他异常可能在现场产生同样的效果,这在处理上很痛苦。因此,我想先解决此问题。

编辑:关键部分归调用TADOStroredProc.ExecProc的线程所有。该线程在处理异常后正常完成,因此,除非我迅速跳入调试器,否则线程会在看到它之前在池中老化,因此上面的ProcessID = 0。将线程停留时间设置为60s而不是10s至少可以告诉我。

最佳答案

首先,我不明白为什么您在后台线程中调用打开ADO存储的proc是“滥用”-它应该可以正常工作,除非您在不同线程的套间或其他消息传递中有困惑(例如,监视线程)通知)。

我不知道是什么导致了您的问题,但是我将在Delphi ADO多线程领域中分享一些经验。 COM/OLE STA消息传递是这里的主要嫌疑人。

后台线程确实应该更好地作为MTA。我不知道Delphi 2010是否单独执行此操作,但是Delphi 2006不会-确保在源代码中查找对CoInitializeEx的调用-如果未调用w/COINIT_MULTITHREADED=$00标志,则该线程被认为是不涉及公寓的,并且通过STA/主线程进行编码(marshal)。其他所有init方法都将为您提供一个不错的STA线程。

你应该:

  • 作为MTA
  • 为您的后台线程提供适当的COM ini//finalization
  • 仅使用创建了
  • 的公寓中的所有ADO组件
  • 不创建其他STA线程(默认情况下,主线程是一个);结合带有其他锁定的消息传递是PITA
  • 过多的原因
  • 永远不要将ADO异步功能与多线程
  • 一起使用

    关于multithreading - 主线程 “blocked on critical section which is abandoned”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4622832/

    相关文章:

    delphi - 等待全局变量改变其值

    android - 如何使图像的一部分透明?

    C、linux - 挂起线程直到一些数据到达

    java - ShutdownHook何时被调用?

    java - Spring - 确保线程池

    delphi - 如何让Delphi重新保存所有表单?

    delphi - 压缩组件

    c++ - OpenCV:如何对带有图像的文件夹进行批处理?

    delphi指针地址

    delphi - 在 Delphi 的 Unicode 版本中 Access 记录的真实缓冲区 - ADO