我使用OmniThreadLibrary获得了多线程应用。我错误地使用OTL在辅助线程中打开ADO存储过程,除非出现错误(大多数情况下甚至是这样)。不幸的是,在这种特殊情况下存在问题。
当我打开一个特定的表单时,我在一个线程中得到一个异常“必须至少有一个字段”将数据集复制到一个kb内存表中,我处理并向监控线程发送一条消息。该消息到达并成功存储在数据库中。当我关闭该表单时,主VCL线程挂起。
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。将线程逗留时间设置为60s而不是10s至少可以让我这样做。
答案 0 :(得分:2)
首先,我不明白你为什么要在后台线程中调用ADO存储过程“滥用” - 它应该完美无缺,除非你在不同的线程中有一些混乱'公寓或其他消息(例如监控线程通知)。
我不知道究竟是什么导致了您的问题,但我将分享Delphi ADO多线程领域的一些经验。 COM / OLE STA消息传递是这里的主要嫌疑人。
后台线程应该更好地作为MTA。我不知道Delphi 2010是否自己这样做,但Delphi 2006没有 - 确保查看CoInitializeEx
调用的来源 - 如果没有调用COINIT_MULTITHREADED=$00
标志,该线程被认为是公寓中立的,并通过STA /主线程进行编组。每个其他的init方法都会为你提供一个很好的STA线程。
你应该:
答案 1 :(得分:1)
我建议您使用CodeSite等日志库来追踪主线程停止的位置。