The situation:
I have an application and a plugin dll both written in delphi 7.
The dll exports 3 functions: createobject:pointer, runobject(instance:pointer), freeobject(instance:pointer).
createobject:pointer creates an instance of an dll-internal workobject and returns the pointer to the object.
runobject(instance:pointer) takes this instance pointer as a parameter and uses the pointer to start some processingfunction in the objectinstance that this instance pointer points to.
freeobject(instance:pointer) takes the instance pointer and frees the internal object that this instance pointer points to.
I did this, so that i can create multiple workobject instances from the plugin dll.
Now, the application sets up 2 workerthreads. While setting up the 2 threads, the plugin dll is dynamically loaded twice via loadlibrary (one for each thread) and the exported functions are given to the thread. (Note: because it's the same DLL with the same filename, the DLL is loaded only once into my application and just the reference count of the loaded dll goes to 2.)
Each workerthread starts, calls CoInitialize(nil) to initialize the com system (because i want to use ado components) and then creates its own dll-internal object via the dllfunction createobject and then calls runobject with the returned instancepointer as parameter.
Now, the code inside runobject uses adoconnection + adoquery components to read from a database.
The adocomponents are created inside the workobject and nothing is shared between the 2 threads... no global vars used.
The problem:
I get strange random accessviolations while the 2 objectinstances, each on its own thread, use their own ado components to read from the DB...!?
Both threads start to read some Databaserows. Then, at some random time and "random place" in the adoquery read code, exceptions are being raised.
"Random place" means, that the exceptions sometimes occur in the call to adoquery.open, sometimes in the call to adoquery.next... the ado code is really simple... it looks like this:
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;
I did some testing:
a) If I use only 1 thread (and so only 1 workobject inside the dll is beeing created) then everything works fine.
b) If I make a copy of the DLL File with another filename but the same code inside this file, and thread_1 loads dll_1 and thread_2 loads dll_2 then these 2 identical dlls are really both beeing loaded into my application and everything works fine.(Note: loadlibrary in this test was called from the context of the mainthread, not the context of each workerthread, but that seemed no problem because no exceptions did occur.)
c) If I don't use the DLL at all and just create my 2 workobjects directly on my 2 threads then everything works fine.
The exceptions only occur when I use adocomponents in 2 separate workobjects that are created on 2 threads and the creationcode of the workobject is inside a dll which is loaded only once into my application.
Questions:
If I call exported functions from a dll, does the loadlibrary call which loaded the dll has to be called from within the context of the thread? I don't think this is the case (see test b) ), but perhaps somebody knows better!?`Could this be causing my problems? If this is the case then there seems to be no way of using functions from one dll from multiple threads!?
Does anybody have an idea what causes these strange exceptions?
Any help/idea/explanation/suggestion greatly appreciated.