winapi 线程在消息传递工作之前需要一些时间来初始化?

发布于 2024-09-25 15:16:26 字数 344 浏览 0 评论 0原文

我有一个按顺序创建线程的主程序: 然后线程B ThreadA(传递ThreadB的ID) 使用CreateThread函数。

线程 A 使用 PostThreadMessage 向线程 B 发送消息。 B 使用 GetMessage 获取消息。

我遇到的问题是 PostThreadMessage 在第一次被调用时随机阻塞并且永远不会返回,有时程序运行良好,有时我运行程序,它在第一个 postthreadmessage 处以 0 CPU 使用率阻塞。但是,如果我在第一个 PostThreadMessage 之前将 Sleep(10) 添加到 ThreadA,我似乎永远不会遇到这个问题。

我对线程和消息的时间安排缺少什么?

I have a main program that creates the threads in order:
ThreadB then
ThreadA (which is passed ThreadB's ID)
using the CreateThread function.

Thread A sends a message to Thread B using PostThreadMessage.
B gets the message using GetMessage.

The problem I am having is that PostThreadMessage blocks randomly the first time it is called and never returns, some times the program funs fine, other times I run the program and it blocks with 0 CPU usage at the first postthreadmessage. However if I add Sleep(10) to ThreadA before the first PostThreadMessage, I never seem to encouter this problem.

What am I missing about the timing of threads and messages?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

素手挽清风 2024-10-02 15:16:26

在线程拥有消息队列之前,您无法向该线程发送消息。在该线程调用 GetMessage 或 PeekMessage 等函数之前,不会创建消息队列。 sleep 所做的就是将发送线程延迟足够长的时间,以便接收线程调用 GetMessage 并设置其消息队列。

顺便说一句,我强烈建议不要使用 PostThreadMessage 因为消息可能会丢失。最好在接收线程上创建一个仅消息窗口(其父级为 HWND_MESSAGE)并向其发送消息。

You cannot send a message to a thread until it has a message queue. Message queues are not created until that thread calls a function such as GetMessage or PeekMessage. What your sleep does is delay the sending thread long enough that the receiving thread has called GetMessage and set up its message queue.

Incidentally, I strongly recommend against using PostThreadMessage as the messages can get lost. It is better to create a message-only window (with a parent of HWND_MESSAGE) on the receiving thread and send messages to that instead.

唔猫 2024-10-02 15:16:26

为了添加安东尼·威廉姆斯的正确答案,我用来处理这个问题的代码如下所示。我有一个类似于 MyThread 的类...

void MyThread::Start()
{
  m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL);
  m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId);
  WaitForSingleObject(m_hResumeMain,INFINITE);
  CloseHandle(m_hResumeMain);
  m_hResumeMain=0;
}

DWORD MyThread::ThreadProc(LPVOID pv)
{
  MyThread* self = (MyThread*)pv;
  return self->ThreadProc();
}

DWORD MyThread::ThreadProc()
{
   MSG msg;
  // Create the thread message queue
  PeekMessage(&msg,0,0,0,PM_NOREMOVE);
  // Resume the main thread
  SetEvent(m_hResumeMain);
  while(GetMessage(&msg,0,0,0)>0){
    if(msg.hwnd){
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    else {
     DoThreadMessage(&msg);
    }
  }
  return 0;
}

问题的关键是您最终不能依赖 Sleep 来保证工作线程得到充分初始化。另外,一般来说,在允许启动线程恢复之前,工作线程通常需要完成一些最少量的工作。因此,在创建线程之前创建一个事件对象,在主线程上等待它,并在初始化完成后在工作线程上向它发出信号。

To add to Anthony Williams correct answer, the code I use to deal with this looks like. I have a class similar to MyThread...

void MyThread::Start()
{
  m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL);
  m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId);
  WaitForSingleObject(m_hResumeMain,INFINITE);
  CloseHandle(m_hResumeMain);
  m_hResumeMain=0;
}

DWORD MyThread::ThreadProc(LPVOID pv)
{
  MyThread* self = (MyThread*)pv;
  return self->ThreadProc();
}

DWORD MyThread::ThreadProc()
{
   MSG msg;
  // Create the thread message queue
  PeekMessage(&msg,0,0,0,PM_NOREMOVE);
  // Resume the main thread
  SetEvent(m_hResumeMain);
  while(GetMessage(&msg,0,0,0)>0){
    if(msg.hwnd){
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    else {
     DoThreadMessage(&msg);
    }
  }
  return 0;
}

The crux of the issue is you ultimately cannot rely on a Sleep to guarantee that the worker thread is sufficiently initialized. Plus, in general there is usually some mimimal amount of work a worker thread needs to have done before the launching thread should be allowed to resume. So create an event object before creating the thread, wait for it on the main thread and signal it on the worker thread once the initialization is done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文