繁体   English   中英

通过COM服务器上的其他线程发送数据时丢失数据-以前在VC6中工作,现在在VS2010中中断

[英]Data being lost when sent via a different thread over COM server - previously worked in VC6, now broken in VS2010

从VC6转换到VS2010时,我遇到了很多小问题,但是解决这一问题时遇到了问题。 下面是将数据从我的类发送到COM服务器时使用的委托。

编辑2:添加了代码以检查varResult。

HRESULT Fire_Msg(BSTR Msg)
{
    CComVariant varResult;
    T* pT = static_cast<T*>(this);
    int nConnectionIndex;
    CComVariant* pvars = new CComVariant[1];

    int nConnections = m_vec.GetSize();

    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
        pT->Lock();
        CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
        pT->Unlock();
        IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
        if (pDispatch != NULL)
        {
            pvars[0] = Msg;
            DISPPARAMS disp = { pvars, NULL, 1, 0 };
            pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
        }
    }

    delete [] pvars;

    // Changed to display what happens to varResult.
    if (varResult.scode != S_OK)
    {
        // Do some error handling...  (later)
        return varResult.scode;
    }
    else
    {
        return varResult.scode;
    }
}

编辑2:从工作或不工作,varResult返回S_OK。 没有不同。

当我在此行中断时,从主进程或线程发送时,数据看起来正确:

pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);

编辑:我有工作和不工作的图片。 它实际上只是表明,从从threadex启动的线程进行调用时,数据已在“ disp”中正确设置,并且在执行“ pDispatch-> Invoke”时没有问题。 工作的

非工作: 非工作 :结束编辑

在另一个应用程序中,我有以下代码来回答调度的数据:

BEGIN_DISPATCH_MAP(CGenRTEvent, CCmdTarget)
    //{{AFX_DISPATCH_MAP(CGenRTEvent)
    DISP_FUNCTION(CGenRTEvent, "OnMsgStr", OnMsgStr, VT_EMPTY, VTS_BSTR)
    DISP_FUNCTION(CGenRTEvent, "OnMsg", OnMsg, VT_EMPTY, VTS_BSTR)
    DISP_FUNCTION(CGenRTEvent, "OnEndRun", OnEndRun, VT_EMPTY, "")
    DISP_FUNCTION(CGenRTEvent, "OnProgress", OnProgress, VT_EMPTY, VTS_I4 VTS_BSTR)
    DISP_FUNCTION(CGenRTEvent, "OnISocket", OnISocket, VT_EMPTY, VTS_BSTR)
//  DISP_FUNCTION(CGenRTEvent, "OnMsg", OnMsg, VT_EMPTY, VTS_PVARIANT)
    //}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

BEGIN_INTERFACE_MAP(CGenRTEvent, CCmdTarget)
    INTERFACE_PART(CGenRTEvent, DIID__IGenRTEvents, Dispatch)
END_INTERFACE_MAP()

void CGenRTEvent::OnMsgStr(LPCTSTR strMsg) 
{
    m_pFrame->OnMsgStr(strMsg);
}

从主线程(在第一个应用程序内部)使用时,会正确引发OnMsgStr。 从其他线程完成时,永远不会引发OnMsgStr。 这在VC6中一直运行良好,但是VS2010不喜欢它。

编辑:我的问题是,如何防止数据丢失? 我相当确定原因与从另一个线程调用此事件有关,但不知道如何解决。

任何建议或意见表示赞赏吗?

提前致谢。

在Paulo Madeira的慷慨帮助下,我能够通过搜索KB280512来解决此问题,这使我进入了由PJ Naughter编写的名为GPSCom的项目。 链接在这里http://www.naughter.com/gpscom2.html 我下载了他的代码,他提供了一个名为“ ATLCPImplMT.h”的免费软件,可以未经修改就以任何形式使用。 根据他的示例,我将代码修改如下:

HRESULT Fire_Msg(BSTR Msg)
{
    CComCritSecLock<CComAutoCriticalSection> lock(m_CPMTCritSec);

    ATL::CComVariant varResult;
    int nConnections = m_Clients.GetSize();

    int nConnectionIndex;
    ATL::CComVariant* pvars = new ATL::CComVariant[1];

    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
        ATL::CComPtr<IDispatch> sp;
        if (SUCCEEDED(GetInterfaceAt(nConnectionIndex, sp)))
        {
            VariantClear(&varResult);
            pvars[0] = Msg;
            DISPPARAMS disp = { pvars, NULL, 1, 0 };
            sp->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
            if (varResult.scode != S_OK)
            {
                // Do some error handling...  (later)
                return varResult.scode;
            }
        }
    }
    delete [] pvars;
    return varResult.scode;
}

这个问题可能是这里提出的问题的重复: ATL COM:从其他线程访问事件方法 但是说句公道话,当我开始搜索时-我不知道搜索正确的单词。 谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM