Проблема в многопоточном вызове ActiveX подпрограммы обратного вызова JavaScript - PullRequest
0 голосов
/ 15 ноября 2011

все.У меня проблемы с программированием ActiveX с помощью ATL.Я пытаюсь создать 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 ERROR (-2147418113 (8000FFFF) Катастрофическая ошибка.)Я что-то пропустил?пожалуйста, помогите мне разобраться.

1 Ответ

2 голосов
/ 15 ноября 2011

JavaScript-движок IE является однопоточным, как и код ATL, вызывающий события. Попросите подпотоку отправить сообщение в ветку, в которой создается ActiveX (например, в дескриптор окна ActiceX, если оно есть), а затем вызвать событие.

...