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

C++ 如何访问线程外的线程数据,c++,windows,dll,multithreading,text-to-speech,C++,Windows,Dll,Multithreading,Text To Speech,问题:我在线程中启动MS文本到语音引擎,以避免DLL_attach崩溃。它启动正常,文本到语音引擎得到初始化,但我无法在线程外访问ISpVoice。如何在线程外访问ISpVoice?毕竟这是一个全局变量 您可以在此处找到XPThreads: 首先,您的问题是,您希望在运行文件的静态初始化器时启动的线程在DllMain运行时已经完成,而您却没有做任何事情来与它同步。当然,如果你正在做一些事情来与它同步,那么你将与我在回复你的 其次,COM接口指针通常是特定于线程的。通常,您不能通过CoCreat

问题:我在线程中启动MS文本到语音引擎,以避免DLL_attach崩溃。它启动正常,文本到语音引擎得到初始化,但我无法在线程外访问ISpVoice。如何在线程外访问ISpVoice?毕竟这是一个全局变量

您可以在此处找到XPThreads:


首先,您的问题是,您希望在运行文件的静态初始化器时启动的线程在DllMain运行时已经完成,而您却没有做任何事情来与它同步。当然,如果你正在做一些事情来与它同步,那么你将与我在回复你的

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

第三,你没有理由在你的DllMain中调用CoUninitialize,因为a你不知道你在哪个线程上被调用,b你没有责任在应用程序拥有的随机线程上调用CoInitialize

第四,调用LoadLibrary是非常糟糕的,原因是我在回答您之前的问题时指出的

因此,总而言之,正如我在回答你的另一个问题时所说,你不能在德莱曼做你想做的事。这不是做这件事的地方。如前所述,当您收到DLL\u进程\u附加通知时,您可以运行一个线程,但在执行此操作时请遵守规则,这样您就不会死锁并在其中加载COM对象。然后,您只能从该线程访问接口指针,并且必须自己进行编组,以便将调用DLL的线程的值传递到COM线程。即使这样,也可能有更好的方法来做你正在做的事情,比如把你正在构建的所有东西都公开为它自己的COM对象,但是你没有给任何人足够的上下文来回答你真正的问题


哦,最后。。。您使用的XPThreads是基于一个有缺陷的假设,即您必须等待从CreateThread返回的线程句柄,您不需要,您可以在创建线程后关闭它,因为您不想等待它。您可能想看看为什么不应该使用CreateThread,而应该使用_beginthreadex。

首先,您的问题是,您希望在运行文件的静态初始化器时启动的线程在DllMain运行时已经完成,但您没有做任何事情来与它同步。当然,如果你正在做一些事情来与它同步,那么你将与我在回复你的

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

第三,你没有理由在你的DllMain中调用CoUninitialize,因为a你不知道你在哪个线程上被调用,b你没有责任在应用程序拥有的随机线程上调用CoInitialize

第四,调用LoadLibrary是非常糟糕的,原因是我在回答您之前的问题时指出的

因此,总而言之,正如我在回答你的另一个问题时所说,你不能在德莱曼做你想做的事。这不是做这件事的地方。如前所述,当您收到DLL\u进程\u附加通知时,您可以运行一个线程,但在执行此操作时请遵守规则,这样您就不会死锁并在其中加载COM对象。然后,您只能从该线程访问接口指针,并且必须自己进行编组,以便将调用DLL的线程的值传递到COM线程。即使这样,也可能有更好的方法来完成您正在做的事情,比如将您正在构建的所有内容公开为自己的COM对象,但是您没有为任何人提供足够的上下文来回答这个问题 你真正的问题


哦,最后。。。您使用的XPThreads是基于一个有缺陷的假设,即您必须等待从CreateThread返回的线程句柄,您不需要,您可以在创建线程后关闭它,因为您不想等待它。您可能想看看为什么不应该使用CreateThread,而应该使用_beginthreadex。

您能指出cour代码失败的地方吗?另外,Dll_Attach有什么问题?请注意,在DllMain中调用LoadLibrary是一个坏主意-windows用于序列化dll加载的全局锁可能会出现大问题。见中的备注。不确定这是否是导致问题的原因。访问问题是由线程引起的,而不是由dllmain引起的。然而,dllmain负责强迫我使用线程,所以间接地说你是对的。你能指出cour代码失败的地方吗?另外,Dll_Attach有什么问题?请注意,在DllMain中调用LoadLibrary是一个坏主意-windows用于序列化dll加载的全局锁可能会出现大问题。见中的备注。不确定这是否是导致问题的原因。访问问题是由线程引起的,而不是由dllmain引起的。然而,dllmain负责强迫我使用线程,所以间接地说你是对的。
#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;
}