使用_beginthread和CreateThread进行多线程处理

Oni*_*ni1 4 c++ winapi

我尝试用C++编写多线程WIN32应用程序,但由于我遇到了困难.其中一个Window Procedure创建一个Thread,它管理该窗口的输出.如果此窗口过程接收到消息(来自其他窗口过程),则应将其传输到其线程.一开始我使用_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;
    }
...
}
Run Code Online (Sandbox Code Playgroud)

使用_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;
}
...
Run Code Online (Sandbox Code Playgroud)

thHallo for CreateThread:

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;
}
Run Code Online (Sandbox Code Playgroud)

thHallo for _beginthread(...):

void thHallo(void *pvoid)
{
   ...
   // The Same like for CreateThread
   ...
   _endthread();
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 7

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

当Windows 2000引入了线程池时,必须这样做.当代码被线程池线程调用时,没有可能的方法来初始化内部CRT状态.相当努力btw,他们必须解决的最难的问题是确保线程停止运行时线程本地状态再次自动清理.许多程序因错误而死亡,Apple的QuickTime是这些崩溃的特别恶劣的来源.

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

使用PostThreadMessage()时存在严重问题.您在_beginthread()代码中使用了错误的参数,这就是它无效的原因.但它有更大的问题.发布的消息只能在消息循环中检索.哪个工作正常,直到它不再是您的消息循环调度消息.在许多情况下,这在GUI应用程序中会发生.简单的例子是使用MessageBox(),DialogBox()或用户调整窗口大小.Windows自身工作的模态代码,用于消息循环.

一个很大的问题是该代码中的消息循环知道有关您发布的消息的bean.他们只是陷入了沉重的困境,消失得无影无踪.该模态循环内的DispatchMessage()调用失败,您发布的消息具有NULL窗口句柄.

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