gpt4 book ai didi

c++ - 使用 _beginthread 和 CreateThread 的多线程

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:10:25 26 4
gpt4 key购买 nike

我尝试用 C++ 编写多线程 WIN32 应用程序,但由于我遇到了困难。其中一个窗口过程创建了一个线程,它管理这个窗口的输出。如果此窗口过程收到一条消息(来自其他窗口过程),它应该将其传输到它们的线程。一开始我使用 _beginthread(...) 函数,但是什么不起作用。然后我用 CreateThread(...) 函数尝试了它,它有效吗?我做错了什么?(我的英语不太好,希望你能理解我的问题)

使用 CreateThread(...) 编写代码:

DWORD thHalloHandle; // global
HWND hwndHallo; // Hwnd of WndProc4
...
LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params ;

switch (message)
{
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
CreateThread(NULL, 0, thHallo, &params, 0, &thHalloHandle);
return 0 ;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...
}

使用 _beginthread(...) 编写代码:

...
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
thHalloHandle = (DWORD)_beginthread (thHallo, 0, &params) ;
return 0;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...

创建线程的 thHallo:

DWORD WINAPI thHallo(void *pvoid)
{
static TCHAR *szMessage[] = { TEXT(...), ...};
// Some Declaration
pparams = (PPARAMS) pvoid;
while(!pparams->bKill)
{
MsgReturn = GetMessage(&msg, NULL, 0, 0);
hdc = GetDC(pparams->hwnd);
if(MsgReturn)
{
switch(msg.message)
{
// case....
}
}
}
return 0;
}

thHallo for _beginthread(...):

void thHallo(void *pvoid)
{
...
// The Same like for CreateThread
...
_endthread();
}

最佳答案

事实证明,_beginthread/ex() 函数极难消除。这在上个世纪是必要的,VS6 是最后一个需要它的 Visual Studio 版本。它是一个创可贴,允许 CRT 为内部 CRT 变量分配线程局部状态。与用于 strtok() 和 gmtime() 的函数一样,CRT 函数维护内部状态。必须为每个线程单独存储该状态,以便在一个线程中使用 strtok() 不会搞砸在另一个线程中使用 strtok()。它必须存储在线程本地状态中。 _beginthread/ex() 确保再次分配和清理此状态。

这已经得到解决,当 Windows 2000 引入线程池时必然如此。当您的代码被线程池线程调用时,无法初始化内部 CRT 状态。顺便说一句,他们付出了很大的努力,他们必须解决的最困难的问题是确保当线程停止运行时线程本地状态再次自动清理。许多程序都因该错误而死亡,Apple 的 QuickTime 是这些崩溃的特别严重的来源。

所以忘记 _beginthread() 曾经存在过,使用 CreateThread() 就可以了。

您对 PostThreadMessage() 的使用存在严重问题。您在 _beginthread() 代码中使用了错误的参数,这就是它不起作用的原因。但它还有更大的问题。发布的消息只能在您的消息循环中检索。哪个工作正常,直到它不再是您的消息循环调度消息。在 GUI 应用程序中,很多情况下都会发生这种情况。简单示例是使用 MessageBox()、DialogBox() 或用户调整窗口大小。由 Windows 本身运行的模态代码抽取消息循环。

一个大问题是代码中的消息循环知道有关您发布的消息的 bean。他们只是掉进了比特桶,消失得无影无踪。该模态循环内的 DispatchMessage() 调用失败,您发布的消息具有 NULL 窗口句柄。

必须改用 PostMessage() 来解决这个问题。这需要一个窗口句柄。您可以使用任何 窗口句柄,主窗口的句柄是一个不错的选择。更好的是,您可以创建一个专用窗口,一个不可见的窗口,它有自己的 WndProc() 来处理这些线程间消息。一个很常见的选择。 DispatchMessage() 现在不会再失败,也解决了您的错误。

关于c++ - 使用 _beginthread 和 CreateThread 的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20899811/

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