簡體   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