我有一个使用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线程。
你应该:
关于multithreading - 主线程 “blocked on critical section which is abandoned”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4622832/