情况:
我有一个应用程序和一个插件dll都是用delphi 7编写的。
dll导出3个函数:createobject:指针、runobject(实例:指针)、freeobject(实例:指针)。
我这样做了,这样我就可以从插件dll创建多个工作对象实例。
现在,应用程序设置了2个工作线程。在设置两个线程时,通过加载库(每个线程一个)动态加载插件dll两次,并将导出的函数分配给线程。(注意:因为它是同一个具有相同文件名的DLL,所以DLL只加载到我的应用程序中一次,并且加载的dll的引用计数为2)。
每个工作线程启动,调用CoInitialize(nil)来初始化com系统(因为我想使用ado组件),然后通过dllfunction创建自己的dll-内部对象,然后用返回的instance指针作为参数调用runobject。
现在,runobject中的代码使用adoconnection + adoquery组件从数据库中读取。
adocomponents是在工作对象中创建的,两个线程之间没有任何共享.没有使用全球范围的vars。
问题是:
当两个对象实例(每个都在自己的线程上)使用自己的ado组件从DB.读取时,我得到了奇怪的随机访问违规行为。
两个线程都开始读取一些Databaserow。然后,在某个随机时间和adoquery读取代码中的“随机位置”,出现异常。
“随机位置”的意思是,异常有时发生在对adoquery.open的调用中,有时发生在对adoquery.next的调用中。密码很简单..。看起来是这样的:
with adoquery do
begin
sql.clear;
sql.add('select * from sometable');
open;
while not eof do
begin
test := fieldbyname('test').asstring;
next;
end;
close
end;我做了一些测试:
如果我只使用一个线程(所以在dll中创建的只有一个工作对象),那么一切都很好。
b)如果我用另一个文件名复制一个DLL文件,但该文件中的代码相同,而thread_1加载dll_1和thread_2加载dll_2,那么这两个相同的DLL实际上都加载到我的应用程序中,一切正常。(注意:这个测试中的加载库是从主线程的上下文中调用的,而不是每个工作线程的上下文,但这似乎没有问题,因为没有出现异常。)
c)如果我根本不使用DLL,只需在我的2个线程上直接创建我的2个工作对象,那么一切都正常。
只有当我在两个线程上创建的独立的工作对象中使用adocomponents,并且该工作对象的创建代码在一个dll中时才会发生异常,这个dll只加载一次到我的应用程序中。
问题:
如果我从dll调用导出函数,是否必须从线程上下文中调用加载dll的加载库调用?我不认为是这样的(见测试b ),但也许有人知道得更清楚!?‘这会不会引起我的问题?如果是这样的话,那么似乎没有办法使用来自多个线程的一个dll的函数!?
有人知道是什么导致了这些奇怪的例外吗?
任何帮助/想法/解释/建议都非常感激。
发布于 2013-11-04 10:16:28
我找到了。问题是,我必须在dllcode IsMultiThread中使用IsMultiThread := TRUE将delphi内存管理器切换到多线程模式!我已经在主应用程序代码中这样做了,但是dll似乎使用了它自己版本的IsMultiThread标志,甚至使用了自己版本的delphi。在now代码中添加了IsMultiThread := TRUE之后,现在一切都正常了。
https://stackoverflow.com/questions/19709551
复制相似问题