- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个事件处理线程类,它允许我从其他线程引发事件而不中断它们的操作。当调用析构函数时,我向线程发送一条退出消息,但它的消息循环似乎没有收到这条消息。
#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/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!