Board index » cppbuilder » Threading and use of ActiveX controls - please help

Threading and use of ActiveX controls - please help

Hi-
In previous posts I reviewed that I have been trying to get a set of
working ActiveX controls working in a multi-threaded program.

If I use the controls in a single threaded program - no problem.
If I use them in a multi-threaded program the simplest call to either
causes an exception.

Previous replies indicated that calls to CoInitialize and
Couninitialize are required to get the apartment model correct before
the calls in to controls could succeed. I tried this and got the same
exceptions.

Perhaps I did not make the calls to init COM correctly or perhaps
there is another way to accomplish this feat. Can anyone enlighten
me??

TIA

 

Re:Threading and use of ActiveX controls - please help


Salutation bart,

Quote
> If I use the controls in a single threaded program - no problem.
> If I use them in a multi-threaded program the simplest call to either
> causes an exception.

At least you know that your ActiveX is working.

Quote
> Previous replies indicated that calls to CoInitialize and
> Couninitialize are required to get the apartment model correct before
> the calls in to controls could succeed. I tried this and got the same
> exceptions.

Well it's more of a security then anything else. The worst case scenario
with a missing apartment is that you will not be able to create a COM
component or the called to the method of the component will always fail.

When you include an ActiveX in a project, it will automatically have an
apartment ready for you. However i find it annoying since the same won't
happen in a standard COM component.

So good rule of thumb is always create an apartement for each new thread or
process.

Quote
> Perhaps I did not make the calls to init COM correctly or perhaps
> there is another way to accomplish this feat. Can anyone enlighten
> me??

Well if i recall correctly you create a new activeX for each thread right?
The only problem i could see is if the ocx is single thread only (meaning
only one thread can ever access the file at anytime). I suppose in that case
the activeX create would fail for the second thread (never test that so i
don't know)

Another point to consider is that you probably use the class wrapper of the
activeX and not an interface pointer. A class wrapper use the dispatch
interfafe with the Invoke method to call indirectly the method of the
activeX. That's automation. One big problem with automation is that you are
never sure if you either invoke the proper method with the proper
attributes. You will tend to get a lot of access violation which are of no
help while debugging.

It might be good to actually use a raw interface pointer on your activeX and
try if it makes a difference.

In each thread you could try this instead :

    IYourActiveX* pActiveX = 0;
    HRESULT hr;

    // The thread start
    CoInitialize(0);

    // Create the activeX, you will have to replace the GUID_ and the IID_
with the proper value of your activeX
    hr = CoCreateInstance(GUID_YourActiveX, 0, CLSCTX_ALL, IID_YourActiveX,
reinterpret_cast<void**>(&pActiveX));

    if( SUCCEEDED(hr) )
    {
        // Call some method
        pActiveX->SomeMethod();

        // Do other stuff

        // Eventually we are done
        pActiveX->Release();
    }

    // And the thread is gone
    CoUinitiliaze();

    Doing so you can check the hr value if you are able to create the
activeX or not and the return value can even be decoded with a microsoft
utility so that can help you know what's going on.

Hope this helps.

Francois Belair

Re:Threading and use of ActiveX controls - please help


Thank you again my friend.
I will experiment with this approach.

I had hoped to use the imported controls, however it does appear that
the wrapper is trapping my calls in a multithreaded environment.
Perhaps the direct approach will be more fruitful..

On Thu, 1 Feb 2001 12:54:52 -0500, "Francois Belair"

Quote
<fbel...@infopharm.ca> wrote:
>Salutation bart,

>> If I use the controls in a single threaded program - no problem.
>> If I use them in a multi-threaded program the simplest call to either
>> causes an exception.

>At least you know that your ActiveX is working.

>> Previous replies indicated that calls to CoInitialize and
>> Couninitialize are required to get the apartment model correct before
>> the calls in to controls could succeed. I tried this and got the same
>> exceptions.

>Well it's more of a security then anything else. The worst case scenario
>with a missing apartment is that you will not be able to create a COM
>component or the called to the method of the component will always fail.

>When you include an ActiveX in a project, it will automatically have an
>apartment ready for you. However i find it annoying since the same won't
>happen in a standard COM component.

>So good rule of thumb is always create an apartement for each new thread or
>process.

>> Perhaps I did not make the calls to init COM correctly or perhaps
>> there is another way to accomplish this feat. Can anyone enlighten
>> me??

>Well if i recall correctly you create a new activeX for each thread right?
>The only problem i could see is if the ocx is single thread only (meaning
>only one thread can ever access the file at anytime). I suppose in that case
>the activeX create would fail for the second thread (never test that so i
>don't know)

>Another point to consider is that you probably use the class wrapper of the
>activeX and not an interface pointer. A class wrapper use the dispatch
>interfafe with the Invoke method to call indirectly the method of the
>activeX. That's automation. One big problem with automation is that you are
>never sure if you either invoke the proper method with the proper
>attributes. You will tend to get a lot of access violation which are of no
>help while debugging.

>It might be good to actually use a raw interface pointer on your activeX and
>try if it makes a difference.

>In each thread you could try this instead :

>    IYourActiveX* pActiveX = 0;
>    HRESULT hr;

>    // The thread start
>    CoInitialize(0);

>    // Create the activeX, you will have to replace the GUID_ and the IID_
>with the proper value of your activeX
>    hr = CoCreateInstance(GUID_YourActiveX, 0, CLSCTX_ALL, IID_YourActiveX,
>reinterpret_cast<void**>(&pActiveX));

>    if( SUCCEEDED(hr) )
>    {
>        // Call some method
>        pActiveX->SomeMethod();

>        // Do other stuff

>        // Eventually we are done
>        pActiveX->Release();
>    }

>    // And the thread is gone
>    CoUinitiliaze();

>    Doing so you can check the hr value if you are able to create the
>activeX or not and the return value can even be decoded with a microsoft
>utility so that can help you know what's going on.

>Hope this helps.

>Francois Belair

Other Threads