Multithreading “主线程”;在被废弃的关键截面上堵塞”;
我有一个多线程应用程序使用。我错误地使用OTL在辅助线程中打开ADO存储过程,除非出现错误(大多数情况下甚至出现错误),否则这些存储过程都可以工作。不幸的是,在这种特殊情况下有一个问题 当我打开一个特定的表单时,我在一个线程“必须至少有一个字段”中得到一个异常,该线程将数据集复制到一个kb内存表中,我处理该表并向一个监控线程发送消息。该消息到达并成功存储在数据库中。当我关闭该窗体时,主VCL线程挂起Multithreading “主线程”;在被废弃的关键截面上堵塞”;,multithreading,delphi,delphi-2010,Multithreading,Delphi,Delphi 2010,我有一个多线程应用程序使用。我错误地使用OTL在辅助线程中打开ADO存储过程,除非出现错误(大多数情况下甚至出现错误),否则这些存储过程都可以工作。不幸的是,在这种特殊情况下有一个问题 当我打开一个特定的表单时,我在一个线程“必须至少有一个字段”中得到一个异常,该线程将数据集复制到一个kb内存表中,我处理该表并向一个监控线程发送消息。该消息到达并成功存储在数据库中。当我关闭该窗体时,主VCL线程挂起 kbMemTable.LoadFromDataset(StoredProc, []); // t
kbMemTable.LoadFromDataset(StoredProc, []); // throws
在调试器中暂停应用程序并查看线程列表,主VCL线程显示:
"Blocked on critical section which is abandoned owned by Process 0"
OTL线程仍然处于活动状态,并且时间不在线程池中,因此除了主线程之外,似乎所有的东西都在工作。我还使用了DevExpress和Raise组件,它们有自己的线程,但没有命名它们(而且似乎不是问题的一部分),这意味着我有12个线程,其中只有5个可以识别
我强烈怀疑Delphi数据库中有什么东西抓住了关键部分,然后由于异常而未能发布它。在我直接使用的Delphi/数据库源代码单元中似乎没有任何关键部分,但显然在某个地方有一个关键部分
这涉及太多的源代码,我的测试应用程序不会显示这种行为
我想了解有关追踪此信息的任何提示。
我目前的想法是切换到调试dcu,并对我能找到的每个关键部分创建进行断点,然后看看会发生什么。我可以解决引发第一个异常的问题,但我担心其他一些异常可能会在需要处理的领域产生同样的影响。所以我想先解决这个问题
编辑:关键部分由调用TADOStroredProc.ExecProc的线程拥有。该线程在处理异常后正常完成,因此,除非我快速跳入调试器,否则线程在我看到它之前就会从池中老化,因此上面的ProcessID=0。将线程的延迟时间设置为60秒而不是10秒至少给了我这个机会。我建议您使用诸如CodeSite之类的日志库来跟踪主线程停止的位置。首先,我不明白为什么您将在后台线程中打开ADO存储的进程称为“误用”-它应该可以完美地工作,除非不同线程的单元或其他消息(例如监视线程通知)中有一些混乱。
我不知道到底是什么原因导致了您的问题,但我将分享一些关于Delphi ADO多线程领域的经验。COM/OLE STA消息是这里的主要嫌疑犯 后台线程应该更像MTA。我不知道Delphi 2010是否自己做到了这一点,但Delphi 2006没有做到这一点——为了确保这一点,请查看对
CoInitializeEx
的调用的源代码——如果不使用Conit\u MULTITHREADED=$00
标志调用,则该线程被认为是单元中立的,并通过STA/主线程封送。其他每一个init方法都会为您提供一个不错的STA线程。你应该:
- 以MTA的形式为您的反向线程提供适当的COM ini-/终结
- 仅使用创建ADO组件的单元中的所有ADO组件
- 不创建其他STA线程(主线程默认为一个);将消息传递与其他锁定相结合是一种太多的PITA
- 切勿将ADO异步功能与多线程一起使用