gpt4 book ai didi

c++ - PostThreadMessage 不起作用

转载 作者:行者123 更新时间:2023-11-30 02:47:52 24 4
gpt4 key购买 nike

我有一个事件处理线程类,它允许我从其他线程引发事件而不中断它们的操作。当调用析构函数时,我向线程发送一条退出消息,但它的消息循环似乎没有收到这条消息。

#include <iostream>
using namespace std;

#include <windows.h>
#define WIN32_LEAN_AND_MEAN

#define ET_EVENTPUSH 7854
#define ET_QUITLOOP 6581
#define EVENT_HANDLER void
typedef void (*EVENT)(LPVOID);

//# event handler thread
class event_thread
{
private:
//vars
HANDLE m_thread; //event loop thread
DWORD m_id; //thread id

//thread procedure
static DWORD WINAPI listener_loop(LPVOID);

public:
//constructor
event_thread();
~event_thread();

//functions
void push_event(EVENT, LPVOID);
};

//# event handler thread
event_thread::event_thread()
{
//create thread
m_thread = CreateThread(NULL, 0, listener_loop, NULL, 0, &m_id);
}
event_thread::~event_thread()
{
DWORD dw;

//stop thread
if (m_thread)
{
dw = GetLastError();
PostThreadMessage(m_id, ET_QUITLOOP, 0, 0);
dw = GetLastError();
WaitForSingleObject(m_thread, INFINITE);
CloseHandle(m_thread);
}
}

void event_thread::push_event(EVENT e, LPVOID p)
{
PostThreadMessage(m_id, ET_EVENTPUSH, (UINT)e, (UINT)p);
}
DWORD WINAPI event_thread::listener_loop(LPVOID param)
{
MSG msg;
#define event_type msg.message
#define event_call ((EVENT)(msg.wParam))
#define event_param (LPVOID)(msg.lParam)

//while thread is alive
while (GetMessage(&msg, NULL, 0, 0))
{
switch (event_type)
{
case ET_EVENTPUSH:
event_call(event_param);
break;
case ET_QUITLOOP:
return 0;
}
}
return 0;
}

EVENT_HANDLER asda(LPVOID as)
{
cout << (int)as << endl;
}

int main()
{
event_thread thr;

int i = 1;
while (!GetAsyncKeyState(VK_NUMPAD1))
{
thr.push_event(asda, (LPVOID)(i++));
Sleep(20);
}

return 0;
}
当我发送退出消息时,

GetMessage 没有返回。在 PostThreadMessage 调用之后使用 GetLastError() 会得到 1444 ERROR_INVALID_THREAD_ID

我不想使用 PeekMessage,因为它使用 100% CPU,也不想使用 Sleep,因为这显然是不好的做法。 p>

谢谢

最佳答案

ERROR_INVALID_THREAD_ID 表示您试图将消息发布到没有消息队列的线程 ID。因此,您要么在线程消息循环运行之前尝试发布,要么在线程已经终止之后尝试发布。

当你的线程开始运行时,它应该首先向自己发送消息以创建一个消息队列,然后设置一个信号来表明它已准备好接收消息,最后进入它的消息循环。在您的类构造函数中,在调用 CreateThread() 之后,它可以在退出之前等待该信号。

试试这个:

#include <iostream>
using namespace std;

#include <windows.h>
#define WIN32_LEAN_AND_MEAN

#define ET_START WM_USER+1
#define ET_EVENTPUSH WM_USER+2
#define ET_QUITLOOP WM_USER+3

#define EVENT_HANDLER void
typedef void (*EVENT)(LPVOID);

//# event handler thread
class event_thread
{
private:
//vars
HANDLE m_thread; //event loop thread
DWORD m_id; //thread id
bool m_ready; // message queue is ready

//thread procedure
static DWORD WINAPI listener_loop(LPVOID);

public:
//constructor
event_thread();
~event_thread();

//functions
bool push_event(EVENT, LPVOID);
};

//# event handler thread
event_thread::event_thread()
{
//create thread
m_ready = false;
m_thread = CreateThread(NULL, 0, &listener_loop, this, 0, &m_id);
if (m_thread)
{
while (!m_ready)
Sleep(10);
}
}
event_thread::~event_thread()
{
//stop thread
if (m_thread)
{
if (!PostThreadMessage(m_id, ET_QUITLOOP, 0, 0))
{
DWORD dw = GetLastError();
...
}
WaitForSingleObject(m_thread, INFINITE);
CloseHandle(m_thread);
}
}

bool event_thread::push_event(EVENT e, LPVOID p)
{
return PostThreadMessage(m_id, ET_EVENTPUSH, (WPARAM)e, (LPARAM)p);
}

DWORD WINAPI event_thread::listener_loop(LPVOID param)
{
event_thread *pThis = (event_thread*)param;

MSG msg;
#define event_type msg.message
#define event_call ((EVENT)(msg.wParam))
#define event_param (LPVOID)(msg.lParam)

PostThreadMessage(pThis->m_id, ET_START, 0, 0);
pThis->m_ready = true;

//while thread is alive
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
switch (event_type)
{
case ET_EVENTPUSH:
event_call(event_param);
break;
case ET_QUITLOOP:
PostQuitMessage(0);
break;
}
}
return 0;
}

如果您不喜欢 Sleep() 循环,您可以将 m_ready 替换为可等待事件,然后使用 SetEvent()WaitForSingleObject()

关于c++ - PostThreadMessage 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22428066/

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