ActiveX多线程调用javascript回调例程出现问题

Trouble in ActiveX multi-thread invoke javascript callback routine

本文关键字:问题 例程 回调 多线程 调用 javascript ActiveX      更新时间:2023-09-26

每个人。我在使用ATL进行ActiveX编程时遇到了一些麻烦。我尝试制作一个activex,它可以将文件从http服务器异步下载到本地文件夹,下载后会调用javascript回调函数。我的解决方案是:运行一个线程M来监控下载线程D,当D完成任务时,M将自己终端并调用IDispatch推断调用javascript函数。*****************有我的代码:*****.******

/* javascript code */
funciton download() {
   var xfm = new ActiveXObject("XFileMngr.FileManager.1");
   xfm.download(
    'http://somedomain/somefile','localdev:''folder'localfile',function(msg){alert(msg);});
}
/* C++ code */
// main routine
STDMETHODIMP CFileManager::download(BSTR url, BSTR local, VARIANT scriptCallback)
{
    CString csURL(url);
    CString csLocal(local);
    CAsyncDownload download;
    download.Download(this, csURL, csLocal, scriptCallback);
    return S_OK;
}
// parts of CAsyncDownload.h
typedef struct tagThreadData {
    CAsyncDownload* pThis;
} THREAD_DATA, *LPTHREAD_DATA;
class CAsyncDownload :
    public IBindStatusCallback
{
private:
    LPUNKNOWN pcaller;
    CString csRemoteFile;
    CString csLocalFile;
    CComPtr<IDispatch> spCallback;
public:
    void onDone(HRESULT hr);
    HRESULT Download(LPUNKNOWN caller, CString& csRemote, CString& csLocal, VARIANT callback);
    static DWORD __stdcall ThreadProc(void* param);
};
// parts of CAsyncDownload.cpp
void CAsyncDownload::onDone(HRESULT hr) {
    if(spCallback) {
        TRACE(TEXT("invoke callback function'n"));
        CComVariant vParams[1];
        vParams[0] = "callback is working!";
        DISPPARAMS params = { vParams, NULL, 1, 0 };
        HRESULT hr = spCallback->Invoke(0,
            IID_NULL,
            LOCALE_USER_DEFAULT,
            DISPATCH_METHOD,
            &params, NULL, NULL, NULL);
        if(FAILED(hr)) {
            CString csBuffer;
            csBuffer.Format(TEXT("invoke failed, result value: %d 'n"),hr);
            TRACE(csBuffer);
        }else {
            TRACE(TEXT("invoke was successful'n"));
        }
    }
}
HRESULT CAsyncDownload::Download(LPUNKNOWN caller, CString& csRemote, CString& csLocal, VARIANT callback) {
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    csRemoteFile = csRemote;
    csLocalFile = csLocal;
    pcaller = caller;
    switch(callback.vt){
        case VT_DISPATCH:
        case VT_VARIANT:{
            spCallback = callback.pdispVal;
        }
        break;
        default:{
            spCallback = NULL;
        }
    }
    LPTHREAD_DATA pData = new THREAD_DATA;
    pData->pThis = this;
    // create monitor thread M
    HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (void*)(pData), 0, NULL);
    if(!hThread) {
        delete pData;
        return HRESULT_FROM_WIN32(GetLastError());
    }
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    CoUninitialize();
    return S_OK;
}

DWORD __stdcall CAsyncDownload::ThreadProc(void* param) {
    LPTHREAD_DATA pData = (LPTHREAD_DATA)param;
    // here, we will create http download thread D
    // when download job is finish, call onDone method;
    pData->pThis->onDone(S_OK);
    delete pData;
    return 0;
}

**************代码结束**********好的,以上是我的部分源代码,如果我在子线程中调用onDone方法,我将得到OLE错误(-2147418113(8000FFFF(灾难性故障。(。我错过什么了吗?请帮我弄清楚。

IE的JavaScript引擎是单线程的,ATL的事件引发代码也是单线程的。让子线程将消息发布到创建ActiveX的线程(例如,如果存在ActiceX窗口,则发布到该窗口的句柄(,然后引发事件。