MFC---摄像头检索以及com组件初始化问题

 获取相机名称列表的函数如下:

std::vector<std::string> getCameraNames() {
        std::vector<std::string> cameraNames;
        HRESULT hr;
        /*HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
        if (FAILED(hr)) {
            std::cerr << "Error initializing COM library." << std::endl;
            return cameraNames;
        }*/

        ICreateDevEnum* pDevEnum = NULL;
        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
        if (SUCCEEDED(hr)) {
            IEnumMoniker* pEnum = NULL;
            hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
            if (hr == S_OK) {
                IMoniker* pMoniker = NULL;
                while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
                    IPropertyBag* pPropBag;
                    hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
                    if (FAILED(hr)) {
                        pMoniker->Release();
                        continue;
                    }

                    VARIANT var;
                    VariantInit(&var);

                    // Get description or friendly name.
                    hr = pPropBag->Read(L"Description", &var, 0);
                    if (FAILED(hr)) {
                        hr = pPropBag->Read(L"FriendlyName", &var, 0);
                    }
                    if (SUCCEEDED(hr)) {
                        // Convert BSTR to std::string and add it to the cameraNames vector.
                        char* bstr = _com_util::ConvertBSTRToString(var.bstrVal);
                        cameraNames.push_back(bstr);
                        delete[] bstr;
                        VariantClear(&var);
                    }
                    pPropBag->Release();
                    pMoniker->Release();
                }
                pEnum->Release();
            }
            pDevEnum->Release();
        }

        //CoUninitialize();
        return cameraNames;
    }

封装的dll中有该函数,mfc,自己测试时正常,其他人使用时却异常,分析原因后是自己使用时是在主线程中调用,而其他人使用时是在其他线程中调用。com组件的初始化有两种模式:

  • COINIT_APARTMENTTHREADED:初始化为单线程公寓模型。
  • COINIT_MULTITHREADED:初始化为多线程模型。

        当使用MFC (Microsoft Foundation Class Library) 时,MFC本身会为主线程进行COM初始化。因此,在MFC应用程序的主线程中,可能会发现即使不显式调用CoInitializeExCoInitialize,某些COM相关操作(如CoCreateInstance)也可能成功。

  1. 线程模型冲突MFC默认使用单线程公寓(STA)模型初始化COM。如果要创建的COM对象需要多线程模型(MTA),那么CoCreateInstance会失败。同样,如果在STA线程中创建了一个对象,而此对象只在MTA中有效,那么也可能会遇到问题。

  2. 其他线程:在MFC应用程序中,只有主线程默认初始化了COM。如果在后台线程中执行COM操作而没有显式初始化COM,那么这些操作可能会失败。

  3. 多次初始化:如果在同一个线程中多次调用CoInitializeExCoInitialize并指定不同的线程模型,可能会导致行为异常。

  4. MFC状态:MFC提供了AfxOleInit函数,该函数初始化COM并将线程设置为STA模式。如果此函数未被调用或失败,那么可能会影响COM操作。

因此,如果是在其他线程种调用dll,就会导致失败。

--------------------------------------------------------------------------------------------------------------------------------

COM定义了两种主要的公寓模型:

  1. 单线程公寓(STA):

    • 在STA中,每个线程都有自己的公寓。
    • STA对象必须始终在创建它的那个线程上访问。这意味着任何其他线程想要与STA对象交互,都必须通过某种消息传递机制将操作委托给那个线程。
    • 这为某些操作提供了序列化,特别是在处理用户界面元素(如Windows Forms或其他UI组件)时,通常只能在特定线程上进行修改。
    • COM使用Windows消息循环来跨线程传递方法调用。
  2. 多线程公寓(MTA):

    • MTA可以由多个线程共享。
    • 在MTA中创建的COM对象必须是线程安全的,因为多个线程可能会同时访问它。

       当说“使用STA模型初始化COM”时,意思是正在设置线程以使用单线程公寓模型。这意味着该线程将拥有自己的公寓,并且在该线程上创建的所有COM对象都将按照STA规则运行。

       通常,如果一个应用程序或线程需要与UI交互或依赖于某些只能在STA模型中运行的COM组件,那么它会使用STA模型。相反,如果性能是主要关注点,并且对象是线程安全的,那么可以选择MTA模型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值