locked
The CoCreateInstance returns E_NOINTERFACE when I try to use a COM object on a thread by using windows application

    Question

  • I want to use a COM object on a thread, but CoCreateInstance() API returns E_NOINTERFACE.

    This problem happened on windows application, it works fine when I call CoCreateInstance() on a thread by using console application.

    part of my code are shown below:
    CMyDlg::CMyDlg() : CDialog(IDD_DIALOG1, NULL)
    {
        m_pIX = NULL;
    }

    void CMyDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
        DDX_Control(pDX, IDC_LIST1, m_listScreen);
    }

    BOOL CMyDlg::OnInitDialog()
    {
        if(FALSE == CDialog::OnInitDialog())
            return FALSE;

        //it works here, CoCreateInstance returns S_OK
        /*HRESULT hr = CoInitialize(NULL);
        if(FAILED(hr)) return hr;

        hr = CoCreateInstance(CLSID_ComCmpnt, NULL, CLSCTX_INPROC_SERVER,
                              IID_IX, (void**)&m_pIX);
        if(FAILED(hr)) return hr;*/

        return TRUE;
    }

    UINT CMyDlg::ThreadProc()
    {
        HRESULT hr = CoInitialize(NULL);
        if(FAILED(hr)) return 0;

        //it return E_NOINTERFACE here
        hr = CoCreateInstance(CLSID_ComCmpnt, NULL, CLSCTX_INPROC_SERVER,
                              IID_IX, (void**)&m_pIX);
        if(FAILED(hr)) return 0;

        CoUninitialize();

        return 1;
    }

    UINT CMyDlg::RealThreadProc(LPVOID pParam)
    {
        CMyDlg *pDlg = static_cast<CMyDlg*>(pParam);
        return pDlg->ThreadProc();
    }

    BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
        ON_BN_CLICKED(IDC_BTN_RUN, &CMyDlg::OnBnClickedBtnRun)
    END_MESSAGE_MAP()

    void CMyDlg::OnBnClickedBtnRun()
    {
        CWinThread *worker = AfxBeginThread(RealThreadProc, this);
    }

     

    please help me out.

    Thursday, August 25, 2011 2:16 AM

Answers

  • JupiterLee wrote:

    I want to use a COM object on a thread, but CoCreateInstance() API  returns E_NOINTERFACE.

    This problem happened on windows application, it works fine when I  call CoCreateInstance() on a thread by using console
    application.

    My guess is, the component you are working with uses so-called legacy  single-threaded model. Such a component can only be created in the main  single-threaded apartment - basically, a thread that was first to call  CoInitialize or similar.

    Check in the registry under

    HKEY_CLASSES_ROOT\CLSID\{Your CLSID}\InprocServer32

    I predict there's no ThreadingModel value under this key.


    Igor Tandetnik

    • Marked as answer by JupiterLee Thursday, September 29, 2011 3:30 AM
    Thursday, August 25, 2011 1:25 PM

All replies

  • S_OK in one thread and E_NOINTERFACE in another thread indicate that there is a marshalling problem. The COM sysytem cannot make a proxy\stub to marshall IX interface.
    Thursday, August 25, 2011 11:36 AM
  • JupiterLee wrote:

    I want to use a COM object on a thread, but CoCreateInstance() API  returns E_NOINTERFACE.

    This problem happened on windows application, it works fine when I  call CoCreateInstance() on a thread by using console
    application.

    My guess is, the component you are working with uses so-called legacy  single-threaded model. Such a component can only be created in the main  single-threaded apartment - basically, a thread that was first to call  CoInitialize or similar.

    Check in the registry under

    HKEY_CLASSES_ROOT\CLSID\{Your CLSID}\InprocServer32

    I predict there's no ThreadingModel value under this key.


    Igor Tandetnik

    • Marked as answer by JupiterLee Thursday, September 29, 2011 3:30 AM
    Thursday, August 25, 2011 1:25 PM
  • There is no "ThreadingModel" under HKEY_CLASSES_ROOT\CLSID\{My CLSID}\InprocServer32

    When I create "ThreadingModel" with value "Apartment", the problem is fixed.

    By the way, what's the difference between "Apartment" and "Single"?

    Thanks a lot

    Thursday, September 29, 2011 6:56 AM
  • JupiterLee wrote:

    There is no "ThreadingModel" under HKEY_CLASSES_ROOT\CLSID\{My  CLSID}\InprocServer32

    When I create "ThreadingModel" with value "Apartment", the problem is  fixed.

    That component is not thread-safe (or at least, it hasn't declared  itself ot be thread-safe, so one has to assume the worst). It's possible  that the component maintains global variables or similar, and doesn't  protect against concurrent access to them (because it doesn't expect to  ever be called on more than one thread). Now, suddenly, you have two  instances of that component running on two different threads, both  accessing that global state. You may now have a race condition in your  application.

    By the way, what's the difference between "Apartment" and "Single"?

    "Apartment" specifies apartment threading model. "Single" is not a valid  value for that registry key, I'm not sure where you got it from.

    For details, see http://support.microsoft.com/kb/150777


    Igor Tandetnik

    Thursday, September 29, 2011 12:38 PM