CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Jun 2004
    Posts
    204

    Accessing COM EXE-server from diffent threads

    Hi everyone,

    I am stuck with a problem: my MFC-application loads dynamically a DLL which accesses a COM-Server from 3 diffent threads. When the main thread calls functions from the COM-server it all works fine but if another thread tries to access any function from the COM-server I receive an error.
    CoInitializeEx(NULL, COINIT_MULTITHREADED) is executed in all threads before accessing the server.
    For test purposes I have written a small programm (also MFC) which does the same as my application (calls same function inside the DLL) but here it works fine.

    Has someone any clue what the issue may be?


    Edit: the code is 8001010e: The application called an interface that was marshalled for a different thread.


    Regards
    Padan.
    Last edited by Padan; July 28th, 2009 at 07:03 AM.

  2. #2
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Accessing COM EXE-server from diffent threads

    Are you accessing this COM server from all your threads using the same pointer?
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  3. #3
    Join Date
    Jun 2004
    Posts
    204

    Re: Accessing COM EXE-server from diffent threads

    Yes, the interface pointer is a member variable.
    The DLL was not written by me but it also works works in another application where it was originally used.

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Accessing COM EXE-server from diffent threads

    You'll need to use the global interface table to access an STA from a different thread.

    See http://msdn.microsoft.com/en-us/libr...29(VS.85).aspx

  5. #5
    Join Date
    Jun 2004
    Posts
    204

    Re: Accessing COM EXE-server from diffent threads

    Thank you, maybe I will try that.
    But I still wonder why the DLL works with 2 programmes and not with the 3rd. If possible I'd prefer not to modify the DLL.

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Accessing COM EXE-server from diffent threads

    Quote Originally Posted by Padan View Post
    Thank you, maybe I will try that.
    But I still wonder why the DLL works with 2 programmes and not with the 3rd. If possible I'd prefer not to modify the DLL.
    You don't need to modify the Dll (e.g. in-proc COM server).

    If the COM server is an STA and you want to call use a pointer to it in different threads, then you need to use the GIT.

    The problem isn't with the dll, it's with the fact that you are calling it from multiple threads.

  7. #7
    Join Date
    Nov 2004
    Posts
    133

    Re: Accessing COM EXE-server from diffent threads

    Quote Originally Posted by Padan View Post
    When the main thread calls functions from the COM-server it all works fine
    I think you are fetching the interface pointer in the main thread, and using it in another thread as well, but this will not work, you should not use a interface pointer fetched in one thread in another thread, you can only do this my marshalling the interface pointer.

    Assuming , that you have IMyInterface *ptrMyInterface, once this interface is fetched in the main thread, before you start the other thread, pass the interface pointer to another thread by
    doing this.

    IStream *pStream = NULL;
    HRESULT hr =::CoMarshalInterThreadInterfaceInStream(IID_IMyInterface,ptrMyInterface,&pStream);

    HANDLE h = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadProc,pStream,NULL,&dwid);

    Then inside the thread, you have to unmarshall this interface pointer

    UINT ThreadProc(LPVOID lp)
    {
    HRESULT hr;
    ::CoInitialize(NULL,COINIT_MULTITHREDED);
    IStream *pStream = (IStream *)lp;
    IMyInterface *ptrMyInterface;
    hr = ::CoGetInterfaceAndReleaseStream(pStream,IID_IMyInterface,reinterpret_cast<void **>(&pEvent));

    //make call using the interface pointer.

    }


    regards
    pradish

  8. #8
    Join Date
    Jun 2004
    Posts
    204

    Re: Accessing COM EXE-server from diffent threads

    Arjay, I changed the code to use the global interface table and do not receive any errors anymore. But the access is very slow so I receive internal timeouts quite often.
    I had to change the DLL because it accesses the COM Exe-server. My programme loads the DLL. And the DLL has multiple threads.

    pradish, thanks for the code. I might possibly try that but there seems to be an issue in the application.

    Might other COM-DLLs conflict with the COM Exe-server, e.g. MSXML?

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Accessing COM EXE-server from diffent threads

    What I am referring to is use the GIT which is what the code that Pradish provided - it's the same technique. So you say, you used the GIT, but didn't use Pradish's code - what code did you use?

    In terms of a slowdown, you might want to review the differences between how STA and MTA COM objects work. In a nutshell, STA objects use a message queuing mechanism to serialize incoming requests. If there are multiple STA COM objects residing in the same apartment, their requests will be serialized in the message queue (and performance may suffer).

  10. #10
    Join Date
    Jun 2004
    Posts
    204

    Re: Accessing COM EXE-server from diffent threads

    I use the following code:

    Code:
    CoCreateInstance(CLSID_StdGlobalInterfaceTable,
    				NULL,
    				CLSCTX_INPROC_SERVER,
    				IID_IGlobalInterfaceTable,
    				(void **)&pGIT);
    			
    
    HRESULT hResult = pGIT->RegisterInterfaceInGlobal( m_pInterface, IID_IMyInterface, &dwCookie);
    ...
    HRESULT hr = pGIT->GetInterfaceFromGlobal( dwCookie, IID_IMyInterface, (void **)&pInterface );
    The code itself works fine.

    There is always only one client for the COM-server, it runs as a MTA though. In the original environment where the DLL is used there are more than one client at a time (up to 10) and the application does have any performance issues.

    It wouldn't matter so much if I'd receive slowdowns when calling functions but the events of the COM-servers sometimes arrive very late (10 - 20 seconds delay).

  11. #11
    Join Date
    Nov 2004
    Posts
    133

    Re: Accessing COM EXE-server from diffent threads

    Hi Padan,

    i am making a wild guess..i may be wrong, but you can check this

    In the CProxy_XXXXXX class
    HRESULT Fire_OnSomeEvent()
    {
    HRESULT hr = S_OK;
    T * pThis = static_cast<T *>(this);
    int cConnections = m_vec.GetSize(); //check this size, does this match with the number of
    clients who have registerd for callbaks, if yes, then the problem is something else.

    in most cases the callbacks take time because they have invalid client address.

    other Trivial issues:
    The pGIT pointer that you are using is a global pointer and you are using therad synchronization primitives to protect the
    GIT form being accessed by multiple threads simultaniously


    regards
    pradish




    regards
    pradish
    Last edited by pradish; July 31st, 2009 at 08:23 AM.

  12. #12
    Join Date
    Jun 2004
    Posts
    204

    Re: Accessing COM EXE-server from diffent threads

    Hello pradish and sorry for the late reply.

    Yes, there is only one client registered and the DLL uses synchronization mechanism but this doesn't block the access to the GIT. Only one thread accesses the COM client inside the DLL (at runtime).
    I still do not know why the DLL works fine with two application and does not with the 3rd.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured