gpt4 book ai didi

c++ - 如何访问线程外的线程数据

转载 作者:可可西里 更新时间:2023-11-01 11:14:53 30 4
gpt4 key购买 nike

问题:我在线程中启动 MS 文本到语音引擎,以避免 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;
}

最佳答案

首先,您的问题是您期望在运行文件的静态初始化程序时启动的线程已经完成,而您的 DllMain() 正在运行,但您没有做任何与它同步的事情。当然,如果您正在做一些与它同步的事情,那么您将遇到我在回复您的 other question 时发布的链接中详细说明的问题。 ...

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

第三,您没有理由在 DllMain() 中调用 CoUninitialize(),因为 a) 您不知道调用的是哪个线程,并且b) 您不负责在应用程序拥有的那个随机线程上调用 CoInitialize()

第四,由于 this link 中指出的原因,对 LoadLibrary() 的调用非常糟糕我在回答您之前的问题时发布的。

因此,总而言之,正如我在回答您的其他问题时所说,您不能在 DllMain() 中执行您想执行的操作。这不是做这件事的地方。正如我之前所说,您可以做的是在收到 DLL_PROCESS_ATTACH 通知时启动一个线程,但在这样做时遵守规则,这样您就不会死锁并在其中加载 COM 对象.然后您只能从该线程访问接口(interface)指针,并且您必须自己进行编码以将值从调用您的 DLL 的线程传递到您的 COM 线程。即使那样,也可能有更好的方法来完成您正在做的事情(例如公开您正在构建的所有内容,因为它是 OWN COM 对象)但是您没有提供足够的上下文让任何人想出答案解决您遇到的真正问题。

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

关于c++ - 如何访问线程外的线程数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2681446/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com