Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在COM中将数据从MTA传递到STA,反之亦然,正确的方法是什么_C++_Multithreading_Winapi_Com_Ipc - Fatal编程技术网

C++ 在COM中将数据从MTA传递到STA,反之亦然,正确的方法是什么

C++ 在COM中将数据从MTA传递到STA,反之亦然,正确的方法是什么,c++,multithreading,winapi,com,ipc,C++,Multithreading,Winapi,Com,Ipc,我有一个多线程应用程序,它可以在MTA中运行。它执行outproc对象的调用(我们将其命名为outproc_OBJ_A),一切正常: 每个线程都调用coinitializex(NULL,COINIT\u多线程) 但是现在,我在dll中还有另外两个com对象-我需要在我的应用程序中使用它。让我们在proc_OBJ_B中命名其中一个。它们的线程模型是单元线程。此外,它还共享OUTPROC_OBJ_A的接口(它使用一些数据作为从.tlb文件导入数据的方法的参数) 当我这样做时(在一个线程中): idl

我有一个多线程应用程序,它可以在MTA中运行。它执行outproc对象的调用(我们将其命名为outproc_OBJ_A),一切正常: 每个线程都调用coinitializex(NULL,COINIT\u多线程)

但是现在,我在dll中还有另外两个com对象-我需要在我的应用程序中使用它。让我们在proc_OBJ_B中命名其中一个。它们的线程模型是单元线程。此外,它还共享OUTPROC_OBJ_A的接口(它使用一些数据作为从.tlb文件导入数据的方法的参数)

当我这样做时(在一个线程中):

idl 1:
接口IData:IDispatch
{
}
coclass数据:IData;
idl 2:(使用idl 1):
接口IOBJ_B:IDispatch
{
void initData([in,out]IData*data);
}
Proc_OBJ_B中的coclass:IOBJ_B;
主要内容:
{
CoInitializeX(空,Conit_多线程);
...
{
//1.)创建INPROC_OBJ_B的实例。
CComPtr pOBJ_B=CreateInstance(INPROC_OBJ_B);
//2.)向INPROC_OBJ_B的某个方法传递一些数据(例如,指向此处创建的另一个com对象的指针)
CComPtr pData=CreateInstance(ConcreteData);
pOBJ_B->initData(pData);
//3.)这里它崩溃了。可能是在pData发布时。
//initData现在为空,不做任何操作。
}
coninitialize();
}
当我这样做的时候,它有时可以很好地工作。但有时,它会导致整个应用程序崩溃,并导致访问冲突。有时它抛出对象\u未连接\u异常


当我在CoInitializeX中将Conit_多线程替换为Conit_APARTMENTTHREADED时,它工作得很好。但我不能在我的应用程序中这样做-整个基础设施都在MTA中

[更新]:示例中有更多伪代码


我做错了什么?

“整个基础设施都在MTA中”只是“我们没有基础设施”的另一种说法。当您开始使用其他人的代码时,这不是一个好地方,线程安全通常是一个非常难以实现的目标,并且永远缺少第三方代码。你描述的灾难完全是倒退的,当你和科尼特公寓躺在一起时,它应该表现得很糟糕。如果改用MTA,COM将创建一个线程,为对象提供一个安全的家。请确保您看到此线程是通过调试器创建的。正确编写的代码(INPROC_OBJ_B的实现)可以在STA和MTA实例化线程时正常工作。所以你有一个bug,问题描述没有提到它或崩溃点。我猜想INPROC_OBJ_B实例化是非COM的,在没有封送或破坏封送的情况下发生。也就是说,错误在那里,但它在其他地方,而不是在您提到的细节中。
[in,out]IData*
这不可能。要么参数是
[in]
,要么它的类型是
IData**
,除此之外,您显示的代码(很少)没有任何错误。问题很可能在于您没有使用的代码。除了Igor提到的不正确的[in,out]注释之外,如果我们假设它实际上是[in],那么您必须理解,在initData方法中,您正在传递一个COM接口引用。如果对象B在其自身释放之前正在使用它,那么它应该对其执行AddRef,例如,如果它在其上保留内部引用,否则当代码释放pData时,分配给B的传入引用后面的内存可能会消失(并导致访问冲突)。如果你想在C++中做多线程/IPC COM,你需要了解更多的COM…通常会使用<代码> CurShansIdTrExthRealTeFieleIn流>代码来在不兼容的公寓之间交换东西。
idl 1:
interface IData : IDispatch
{
}

coclass ConcreteData : IData;

idl 2: (uses idl 1):
interface IOBJ_B : IDispatch
{
    void initData([in, out] IData* data);
}

coclass INPROC_OBJ_B : IOBJ_B;

main:
{

    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ...

    {
        // 1.) Create instance of INPROC_OBJ_B.
        CComPtr<IOBJ_B> pOBJ_B = CreateInstance(INPROC_OBJ_B);
        // 2.) Pass to some method of INPROC_OBJ_B some data (For example, pointer to another com object created here.)
        CComPtr<IData> pData = CreateInstance(ConcreteData);

        pOBJ_B->initData(pData);

        // 3.) Here it crashes. Probably on release of pData. 
        // initData now is empty and does nothing.
    }

    CoUninitialize();
}