CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 23
  1. #1
    Join Date
    Dec 2003
    Posts
    244

    Cool Com within Thread

    Hi,
    I have declared the interface pointer as a class variable and called CoCreateInstance in thread of that class .

    Is there any problem with this way ?

    My COM object is based on aparment threading model.

    My question is: I am using Single Threaded Apartment , will below mentioned code work ?

    Example Code ( Don't go on syntax consider the logic )

    Class CClient
    {
    public:
    CClient();
    ~CClient();

    Begin();
    IMyInterface* pMyInterface ;
    static UINT StartThread(LPVOID pParam);
    }
    CClient::CClient()
    {
    CoInitialize(NULL);
    }

    CClient::~CClient()
    {
    CoUninitialize(NULL);
    }

    CClient::Begin()
    {
    AfxBeginThread(StartThread,(LPVOID)this);
    }
    CClient::StartThread(LPVOID pParam)
    {
    CClient*pClient=(CClient*) pParam;
    CoCreateInstance(CLSID_MyInterface, NULL,CLSCTX_ALL,
    IID_IMyInterface, (void**)(IUnknown**) &pMyInterface );


    }

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Com within Thread

    The interface pointer will be valid in context of thread it has been got (i.e. in its apartment). Trying to use it in other thread (i.e. apartment) you'll get error.

    Do not forget initialize apartment with CoInitialize().
    Last edited by Igor Vartanov; November 17th, 2005 at 04:07 AM.
    Best regards,
    Igor

  3. #3
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    You are right , I should have called CoInitialise() and CoUnitialise() in Thread function.


    So According to you it's not possible to declare the Interface Pointer as a class variable and call CoCreateInstance in thread . right ?

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Com within Thread

    Quote Originally Posted by navinkaus
    So According to you it's not possible to declare the Interface Pointer as a class variable and call CoCreateInstance in thread . right ?
    It's possible of course. But it would operate correctly only in one thread. I already explained why - interface pointers adhere their apartments, it doesn't matter what type of memory they reside in.

    The class member is not worse or better choice, 'cause it's just a memory cell.

    You might describe your task in more detailed manner - just to give us a chance to give you a better advice.
    Best regards,
    Igor

  5. #5
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    Re: Com within Thread

    Quote Originally Posted by navinkaus
    So According to you it's not possible to declare the Interface Pointer as a class variable and call CoCreateInstance in thread . right ?
    It is of course possible. Why not?

    One a side note, don't use raw interface pointers, use smart pointers like CComQIPtr, or CComPtr.

    Like this -
    Code:
    Class CClient
    {
    public:
      // ...
    
      // Use smart pointer - CComQIPtr
      CComQIPtr <IMyInterface> pMyInterface ;
      
    };
    And usage...
    Code:
    CClient::StartThread(LPVOID pParam)
    {
      CClient*pClient=(CClient*) pParam;
      CoInitialize (NULL);
    
      if (SUCCEEDED (pMyInterface.CoCreateInstance (CLSID_MyInterface)))
      {
    	pMyInterface->SomeMethod ();
    
    	// Done?
    	pMyInterface.Release ();
      }
      
      ::CoUnintialize ();
    }
    As you can see, the smart pointer is easy to use, simple to read and has reduced the parameters for creating an instance from 5 to 1.

  6. #6
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    Siddhartha, here You went into the code where as I was looking to know something different, I know that there are various benefits of using Smart Pointers ( like allocation of memeory , release of memory etc ) .

    But thing is that.

    Due to a situation It is neccessary for me declaring the Interface Pointer as class variable and calling CoCreateInstance in Thread.

    Now Point were :

    1. Can I use methods of objects in both threads ?


    Earlier Object was not behaving properly , After calling Coinitailize() and CoUnitialize() in thread also I am able to use the methods in main thread.

    Since I am not good in COM threading Models so just wanted to know one simple question.


    Is it possible to use object in the way which I mentioned in my code.

    If still you are not able to understand the situation let me know , I will put this problem in altogther in a different way with real situation ( which is little long to specify ).

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Com within Thread

    Quote Originally Posted by navinkaus
    Now Point were :

    1. Can I use methods of objects in both threads ?
    Do not be confused with methods and objects. C++ objects and their methods can be used in multithreaded environment. But STA-adherent interface pointer must either be used in its own STA or (in case you intend to call its methods in another thread) it has to be marshalled to that thread.

    In my practice I use simplified cross-thread marshalling in case my interface is used inside the same process.

    Code:
    class CSome
    {
        . . .
        IMyInterface* m_pi;
        IStream*      m_stream;
        . . .
    };
    
    void CSome::Begin()
    {
         if( !m_pi )
            CoCreateInstance( ... ); // here we create instance and get interface
         CoMarshalInterThreadInterfaceInStream( ... , &m_stream ); // here we immerse it into stream
         CreateTread( 0, 0, ThreadProc, this,... );
    }
    
    DWORD WINAPI ThreadProc(LPVOID lpv)
    {
        IMyInterface* piLocal = NULL;
        CSome* pSome = (CSome*)pSome;
        CoInitialize();
        CoGetInterfaceAndReleaseStream(pSome->m_stream, ... , &piLocal); // here we get it emerged out already cooked
        // now! fire it
        piLocal->SomeMethod();
        . . .
    }
    Last edited by Igor Vartanov; November 17th, 2005 at 05:47 AM.
    Best regards,
    Igor

  8. #8
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    Re: Com within Thread

    Quote Originally Posted by navinkaus
    Siddhartha, here You went into the code where as I was looking to know something different,
    If you read my sample - you would see that it is answered therein.
    Quote Originally Posted by navinkaus
    Due to a situation It is neccessary for me declaring the Interface Pointer as class variable and calling CoCreateInstance in Thread.
    Well... The situation is aviodable in every case.
    Quote Originally Posted by navinkaus
    1. Can I use methods of objects in both threads ?
    Both? Yes, after initializing the COM Library in each as Igor already answered.
    Quote Originally Posted by navinkaus
    Is it possible to use object in the way which I mentioned in my code.
    Yes... But note that when you do CoCreateInstance you create a new object... The interface pointer is simply pointing to it.

    If one thread overwrites a valid interface pointer assigned aby another - you leak an object.
    Quote Originally Posted by navinkaus
    If still you are not able to understand the situation let me know , I will put this problem in altogther in a different way with real situation ( which is little long to specify ).
    Real situation really helps... For one, I see no reason why you are using raw pointers...
    Last edited by Siddhartha; November 17th, 2005 at 06:08 AM.

  9. #9
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    First of All, I am really very much thankful to both of you for providing your feedback on my questions ( might be stupid ) .

    Now I tell you the real simulation.

    Code:
     Class  CTableObject
    {
          public:
          IMyInterfacePtr pMyInterace;
          CTableObject(CString strTableName);
          ~CTableObject();
         EncryptDecryptTable();
         
    };
    
    CTableObject::CTableObject(CString strTableName)
    {
         CoInitialize(NULL);
         pMyInterace.CreateInstance(__uuidof(MyInterface));
         /*
    The reason of creating Interface Pointer as a member varialbe is , it's constructor takes too much time ( again buisness logic ) and since it is heavily used in the class so I declare it again and again it make this class too much slow that's I have declared it as a member variable */
         /*
     
       /// Logic goes here 
    }
    
    CTableObject::EncryptDecryptTable()
    {
        pMyInterace.EncryptDecrypt(/* Data */);
    }
    
    CTableObject::~CTableObject()
    {
           CoUnitialize();
    }
    
    
    CClient
    {
        public:    
        CTableObject  *pPrdouctTable,*pCustomerTable........10 objects;
        static UINT StartThread(LPVOID pParam);
        PerformSomeOperation();
    };
     
    
    CClient::StartThread(LPVOID pParam)
    {
       Coinitialize(NULL ); 
       CClient*pClient=(CClient*) pParam;
        pClient->pTableObject= new CTableObject("Product");
        pClient->pCustomerTable= new CTableObject("Customers");
        Couninitialize();
    
    }
    
    CClient::PerformSomeOperation()
    {
        pTableObject.EncryptDecryptTable();
    }
    Now Since My COM Class takes lot of time to create itself so it is obvious CTableObject Class will take now. There are lot of CTableObject objects so I put it in thread to initialize all CTableObject mean while user will get the dialog and can play with it ( on the background objects are being created ).

    This is the real simulation ( flow ).

    Whether I use raw interface pointer or smart pointers situation is same.

    That is :

    Interface is being created in one thread

    and methods are called in different thread.

    Let me know if you want to anything more .
    Last edited by Siddhartha; November 17th, 2005 at 07:26 AM.

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Com within Thread

    All essential things on between-thread interface usage have already been said. You have to marshal iterface pointer to use it out of its STA. The choice of the way you do it is left on your own.

    Interface marshalling could affect whole performance because of method parameters data marshalling.

    Maybe more appropriate solution might look like you create all working interfaces in main thread, but you run that for-a-while-dialog-to-play-with in a separate thread.
    Best regards,
    Igor

  11. #11
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    But one strange thing, Without doing marshalling , It is working...If you want I could send you the sample code.

    Quite Strange na ........

    I just put the Coinitialize() in the thread also.

  12. #12
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    Re: Com within Thread

    Yes... That shouldn't really be a problem.

    I haven't yet seen a case where interface pointers used across thread boundaries (with COM initialized in the threads) don't work unless marshalling is done.

    AFAIS, it is a non-issue.

  13. #13
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    Siddhartha, so do you mean without marshalling it will work ?

  14. #14
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    Thanks both of you for sharing your views.

    Also I got a very useful link which describes things some of them which we have already covered , but would like to share with you.

    http://msdn.microsoft.com/library/de...57fd794809.asp

    Also I am doing some R & D on this so we will get back to you as soon as I get something more interesting.

  15. #15
    Join Date
    Dec 2003
    Posts
    244

    Re: Com within Thread

    The link is really very good , it answers all the question of mine but I didn't understand one thing.

    " To handle calls from other processes and apartments within the same process, each single-threaded apartment must have a message loop. This means that the thread's work function must have a GetMessage/DispatchMessage loop. If other synchronization primitives are being used to communicate between threads, the Win32 function MsgWaitForMultipleObjects can be used to wait both for messages and for thread synchronization events. The Platform SDK documentation for this function has an example of this sort of combination loop."

    Do I need message loop in my thread ? and why ?

Page 1 of 2 12 LastLast

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