如何访问线程外的线程数据

Ste*_*ger 1 c++ windows dll multithreading text-to-speech

问题:我在一个线程中启动MS Text-to-speech引擎,以避免DLL_attach崩溃.它开始很好,文本到语音引擎被初始化,但我不能访问线程外的ISpVoice.如何在线程外访问ISpVoice?毕竟这是一个全球变量......

你可以在这里找到XPThreads:http: //www.codeproject.com/KB/threads/XPThreads.aspx

#include <windows.h>
#include <sapi.h>
#include "XPThreads.h"


ISpVoice * pVoice = NULL;

unsigned long init_engine_thread(void* param)
{
Sleep(5000);
    printf("lolthread\n");



    //HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    HRESULT hr = CoInitialize(NULL);

    if(FAILED(hr) )
    {
        MessageBox(NULL, TEXT("Failed To Initialize"), TEXT("Error"), 0);
        char buffer[2000] ;
        sprintf(buffer, "An error occured: 0x%08X.\n", hr);
        FILE * pFile = fopen ( "c:\\temp\\CoInitialize_dll.txt" , "w" );
        fwrite (buffer , 1 , strlen(buffer) , pFile );
        fclose (pFile);
    }
    else
    {   
        printf("trying to create instance.\n");
        //HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **) &pVoice);
        //hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **) &pVoice);
        //HRESULT hr = CoCreateInstance(__uuidof(ISpVoice), NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void **) &pVoice);
        HRESULT hr = CoCreateInstance(__uuidof(SpVoice), NULL, CLSCTX_ALL, IID_ISpVoice, (void **) &pVoice);
        if( SUCCEEDED( hr ) )
        {
            printf("Succeeded\n");
            hr = pVoice->Speak(L"The text to speech engine has been successfully initialized.", 0, NULL);
        }
        else
        {
            printf("failed\n");
            MessageBox(NULL, TEXT("Failed To Create COM instance"), TEXT("Error"), 0);
            char buffer[2000] ;
            sprintf(buffer, "An error occured: 0x%08X.\n", hr);
            FILE * pFile = fopen ( "c:\\temp\\CoCreateInstance_dll.txt" , "w" );
            fwrite (buffer , 1 , strlen(buffer) , pFile );
            fclose (pFile);
        }
    }






return NULL;
}


XPThreads* ptrThread = new XPThreads(init_engine_thread);


BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
    //init_engine();
    LoadLibrary(TEXT("ole32.dll"));
    ptrThread->Run();
    break;
case DLL_THREAD_ATTACH:
    break;
case DLL_THREAD_DETACH:
    break;
case DLL_PROCESS_DETACH:
    if(pVoice != NULL)
    {
        pVoice->Release();
        pVoice = NULL;
    }
    CoUninitialize();
    break;
}
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

Len*_*ate 5

首先,您的问题是,当您的DllMain()运行时,您正在运行文件的静态初始化程序运行时启动的线程,但您却无法与其同步.当然,如果您正在做一些与之同步的事情,那么您将会对我在回复您的其他问题时发布的链接中详细说明的问题进行抨击......

其次,COM接口指针通常是线程特定的.通常,您不能通过CoCreateInstance()或获得一个线程QueryInterface(),然后只在另一个线程中使用它.为了能够在另一个线程中使用一个接口指针,你需要使用类似的东西将它封送到该线程CoMarshalInterface()(参见这里).但是在你能够做到这一点之前,你需要确保你已经在线程上初始化了COM,并且由于我在回答你之前的问题时提出的所有原因你不能这样做.

第三,你没有理由CoUninitialize()在你的电话中调用DllMain()a)你不知道你正在调用什么线程和b)你不负责调用CoInitialize()应用程序拥有的随机线程.

第四,由于我在回答你之前的问题时发布的链接LoadLibrary()指出的原因,所以调用非常糟糕.

因此,总而言之,正如我在回答您的其他问题时所说,您无法做您想做的事情DllMain().它不是这样做的地方.正如我之前所说,你可以做的是在你收到DLL_PROCESS_ATTACH通知时运行一个线程但是当你这样做时遵守规则,这样你就不会死锁并在那里加载你的COM对象.然后,您只能从该线程访问接口指针,并且您必须进行自己的编组操作,以便将调用DLL的线程中的值传递给COM线程.即便如此,你可能还有一种更好的方法可以做你正在做的事情(例如暴露你正在构建的所有东西,因为它是自己的COM对象)但是你没有给任何人提供足够的背景来提出答案你遇到的真实问题.

哦,最后......你正在使用的XPThreads是基于有缺陷的假设,你必须等待你从中获得的线程句柄,你CreateThread()没有,你可以在创建线程后关闭它你没有兴趣等待它.您可能想看看这个问题,看看为什么你可能不应该使用CreateThread(),而应该使用_beginthreadex().