My name is Nathaniel, and I had a former topic dealing with a
problem with using multi-threading in VB6.0. Essentially the problem
i'm experiencing is that I created a C++ DLL which creates a thread.
Now, this thread calls back into a VB6.0 function. The problem is, that
visual basic uses the apartment threading model, which doesnt allow
other created threads to use its functions, but I'm told that this can
be worked around if the VB Runtime can be initialized for the new
thread, and from what I understood in my former thread; this can be
achieved using ActiveX dll components.
So, from what I understand I need to call a VB dll ActiveX component, I
chose to create my own empty ActiveX dll component, if I create an
instance of this empty compoents class (the class contains one function
that does nothing) in my new thread will this cause the VB Runtime to
be initialized for my new thread? Or do I have to use a specific
ActiveX component?
Also in the former thread I saw some source code that looked like it
had been written in VB, do I need to place my empty class instantation
code in the VB callback function? or can I place it in the beginning of
my C++ DLL new thread, which calls a callback function written in VB.
I'm just wondering becuase the latter is more effecient in that, I dont
need to reinitialize the VBruntime via an instantation of my ActiveX
component everytime the VB callback function is called from my new C++
DLL thread?
Sorry that I started a new topic, I thought that since the other topic
got burried, that it would likely not be looked at as much, I took such
a long time to respond becuase I had to do some background reading
about ActiveX, OLE, COM whaterever its name now is, (I believe its
ActiveX)
Thank you very much again, everybody's been really helping me out with
this nasty problem
Nate
Not an ActiveX DLL, but an ActiveX EXE. A DLL runs "in-process," while an
EXE runs "out-of-process." Your code also needs to active some non-blocking
mechanisms (easiest is to use a timer or similar to actually call executing
code).
--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
Thank you very much for your help, I'm not quite sure I understand what
you mean? Do I just activiate a Timer object to initialize the VB
Runtime to allow my c++ DLL function to properly callback my VB
callback function? Or do I use it as a polling mechanism?
Currently, I'm trying to use callback a function which exists in my VB
program, and which I call from my C++ DLL function. The only catch is
that I call back into the VB callback function from a seprate thread
which was started in the DLL, so its like trying to implement free
threading under an apartment threading model. VB hasnt liked it when I
try calling any functions it contains from a thread created in my C++
DLL, however I've been told that using activeX dll (or exe's) can be
used to get around this.
Currently, I've tried creating an instance of just an empty ActiveX dll
which I've created, I placed just a simple message box function in it
to prove I could get an instance of the ActiveX object and execute one
of its members from C++. This works great, but from what i understand,
by creating an instance of a ActiveX dll created by VB, it is suppose
to also initialize the VB runtime, allowing me to call one of my VB
callback functions from my new thread. Howver, when I tried to call the
function, it caused my app to go into deadlock. I also tried changing
the activeX component I created to create some other VB objects, from
VBRUN.error, or VBA.globals. I tried creating new instances of these
classes in my one method (which also displays my mesage box, the method
had been called for debug purps), then when I tried to re-run the
activeX component in my new thread in my C++ DLL, it failed. Also, The
VB Callback function wouldnt run, and caused the VB to stop working
when it tried to callback into it from my thread created in my C++ DLL.
Is there something else I'm missing? Do I need a sapecific COM object
that VB provides? Or do I need to create a specific class instance to
cause the VBRuntime to be loaded?
Thanx for everyone's help again.
Nate
> Currently, I'm trying to use callback a function which exists in my VB
> program, and which I call from my C++ DLL function.
You will have to instantiate a COM-Object inside your VB
Callback-Function each time! you enter this Function, before
you can touch functionality of the VBRuntime (pretty much
everything is tabu, excepting 'Beep').
( Instancing needs between 5 and 50盜 (micro not mili) -
so if you call back high frequently, then you should look
at the processorload if that's ok, or do some maths before.)
That means also, that you have to ensure, that even the instancing
is done without touching the VBRuntime - that's only possible over
OLEAPIs (CoInitialize, CoCreateInstance, ...) wich you will
have to define in a TypeLib first.
A successful instancing will then initialize the ThreadLocalStorage
for you (under the hood) - so after that, you can begin to use the
VBRuntime. The stablest way is, to work directly inside the VB-
COM-Object, wich was just instantiated for TLS-Init.
If you want to do something in the VB-Main-Thread from there,
you will have to use either CoMarshalThreadInterfaceInStream
(and its Counterpart) - or you use PostMessage-Calls.
Recommendation:
It is easier, to span the threads from inside VB and call from
there (from inside the VB-ThreadClass) into a (threadsafe)
C-Dll, than the opposite direction (wich you want to try).
Olaf
If you want to use the workaround that I suggested, you MUST use an ActiveX
EXE, not a DLL. And, code in methods in your AxEXE must exit, so they don't
block the calling code. You can subordinate the actual code in these AxEXE
methods to code that is called from a timer IN the AxEXE, where the timer is
enabled by the method call.
This isn't hard to get working, and I suspect that there may be examples
available online.
It's also true that an ActiveX EXE will provide a multi-threaded VB
environment, but the use of non-blocking calls is only a necessity for
threads that are given a life of their own (i.e. ones not automatically
created just to service a specific method call, or retrieved from a thread
pool for a specific method call).
Having said that, I'm not certain how a separate process would really help
the OP. I think my suggestion would be to delegate the call-back to the main
thread by posting it a message. There are guidelines somewhere (can't find
the link now) for writing a safe call-back that just posts such a message,
and does nothing else.
Tony Proctor
"Dick Grier" <dick_grierNOSPAM@.msn.com> wrote in message
news:%23WeaDfX...@TK2MSFTNGP05.phx.gbl...
And, the DLL wrapper that is created doesn't run "in-process," it simply is
an EXE with a different extension. However, this would solve the design
issue that I mentioned... Com+ (awkward as it is) handles these things.
I've never been a fan; I'm not an "enterprise" type.
Dick
Thanx for the suggestion and example, I've looked into the coffee
example and thought of a way to possibly implement callbacks from a
in-process thread. I dont know if it would work, but what I was
thinking of was setting up a ActiveX exe, and in my new thread which
was started in my C++ DLL, i would create an instance of a "connector"
class which would simply act as a way to retrieve a common class
instance which would be used as a mediator of my callback information.
for example:
In my VB app, I create an instance of a "connector" class, which has a
method, that creates/retrieves an instance of a class which will handle
passing off the callback to VB. Then using raise events in my calback
method, I can callback into a VB class method to handle the event(same
as the cofee example). So the question becomes how do I call the
function which contains the raise events? In the coffee example they
use a timer without an interface ("Xtimer" as they called it), instead
what I was hoping I could do is create an instance of a "connector"
(which will have a method to pass back the same instance of the class
which handles my passing off of the callback to VB) in my new thread
(which was started in my c++DLL) and call the method which contains the
raise events, just like the "Xtimer" has to do in the cofee example.
In the coffee example, the address of the method which contains the
raise events function is passed to the WIN API, now I'm hoping to do
the same, except instead of passing in the address of the method to
cause the raise event, I'm instead calling the method that contains the
raise events function from my new thread. Would this implementation be
possible? (its kind of like using an in-process thread to call
something out-of-process, and back into the original process of a
different thread)
I also thought that matthew curland had an in-process multi-threading
hack. I'm told it will respond faster than the out-of-process method,
and it looks easier to implement, but is it unsafe to use? will it
cause VB to crash? If anyone is familular with his hack, do i use the
type-library he has, or can I create my own in order to not call the VB
runtime before it is initialized/ or before thread local storage is
initialized for my new thread (inorder to get my own copy of VB
globals, to suffice the apartment model)
Thanx for everyones help with this problem :)
Nate
> I also thought that matthew curland had an in-process multi-threading
> hack. I'm told it will respond faster than the out-of-process method,
Yep.
> and it looks easier to implement, but is it unsafe to use? will it
> cause VB to crash?
No, if implemented the right way, then it is safe.
> If anyone is familular with his hack,
I've already posted you some background info regarding
the requirements of VB-InProcess-Threading.
> do i use the type-library he has, ...
No, you can also use Eduardo Morcillos OleLib.tlb, to
do safe InProcess-Threading with VB.
This Example demonstrates the usage of CreateThread with VB6,
including SharedArrays and Synchronization using CriticalSections:
www.datenhaus.de/Downloads/CreateThreadAPI.zip
Olaf
I have to thank everyone with their help they gave me in this thread
and many others regarding this VB 6.0 inprocess multi-threading hack. I
finally got it working, my active X DLL uses a support DLL which I
created in C++ that allows large interprocess messages to be conveyed
easily between threads. It calls a clients message handler to deal with
the incoming interprocess messages. I need to really thank Matthew
Curland for providing the typelibrary (indirectly through Vlad, a
poster in a previous thread regarding this issue) and Vlad as well for
allowing me to see his approach in using this method of inter-apartment
thread communication. If anyone wants to use this activeX Component to
allow for IPC within their VB 6 apps, I'll get the documentation and
final touches to it soon and post the link back here.
Thanx again :)
NATE
James
"Nate, Nano" <nan...@gmail.com> wrote in message
news:1166168537....@79g2000cws.googlegroups.com...