- 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/
我有一个事件处理线程类,它允许我从其他线程引发事件而不中断它们的操作。当调用析构函数时,我向线程发送一条退出消息,但它的消息循环似乎没有收到这条消息。 #include using namespac
我有三个问题。 1. 将 PostThreadMessage 用于 CWinThread 是否安全? 2. 使用 SendMessage 安全吗(在两个应用程序之间)? 消息可以消失吗?SendMes
我不太确定这是否是正确的方法(我是爱好者)。我想将消息发布到循环 GetMessage() 并根据消息执行某些操作的工作线程。我知道我必须将 postthreadmessage() 与该工作线程的句柄
对于 WPF 应用程序,Application.Run 内部是否存在经典的消息循环(在 Windows 的 GetMessage/DispatchMessage 意义上)?是否可以使用 PostThr
今天,我看到了这样一段代码: void Foo() { MyMsgStruct myMsg; /* omission for simplicity */ /* send to
我想向作为另一个进程(特别是作为 Windows 服务)运行的线程发送消息。我已阅读 PostThreadMessage 的文档但有些事情我不清楚。 如何获取服务线程的句柄? The system o
我的 C++ 应用程序中有一个(静态)线程,它经常执行某些操作。为了在线程和我的应用程序之间交换信息,我使用方法 PostThreadMessage 和 PeekMessage。 由于某些原因,我不能
我想使用 Windows 的消息队列功能将结构发送到另一个线程。但是我发现postthreadmessage函数只提供了两个整型参数,lparam和wparam供我传递参数。所以我决定把struct的
我正在尝试使用 WM_COPYDATA 将数据从一个应用程序发送到另一个应用程序。这两个应用程序都是控制台并且没有窗口。我可以很好地发送用户消息。当我尝试发送 WM_COPYDATA 并设置数据结构或
我想升级我的 MFC 生产代码以使用 std::shared_ptr调用其他窗口或线程时的智能指针。此类电话是 SendMessage , PostMessage和 PostThreadMessage
在 PostThreadMessage 中,我的线程 ID 是正确的,但我收到错误 1444(“无效的线程标识符。”)。 有人知道怎么解决吗? 最佳答案 操作系统是线程 ID 是否有效的权威,因此如果
我正在将应用程序移植到 Mac OS X。 我也需要在 Mac OS X 上执行以下任务。线程A需要向另一个线程B的消息队列投递消息。这些消息也涉及一些自定义消息。在像 EXIT_LOOP 这样的特定
我正在处理一些遗留代码,这些代码使用 MFC 的 UI 线程来实现管理器线程-工作线程机制。代码过去在 MFC GUI 应用程序下运行,但现在它在一个单独的 dll 中,并且可以从 GUI 应用程序和
好的,我正在使用 CreateRemoteThread/LoadLibrary 将一些代码注入(inject)到另一个进程中“把戏”。 我最终得到了一个线程 ID,以及一个带有我选择的 DLL 的进程
我有一个使用 Boost 1.47.0 的 Visual Studio 2008 C++ 项目,我需要在其中获取 boost::thread 的 native Windows ID 以传递给 Post
我正在尝试启动 iexplore.exe 让它运行 5 秒钟,然后再次将其关闭。 iexplore 打开很好,但是当我调用 PostThreadMessage 时它没有关闭。谁能看到我做错了什么?这是
我有一个单服务器多客户端 udp 应用程序。有一个线程(thread#1)和一个套接字(socket#1)连续接收来自 client#1 的数据。这个接收线程的任务是在它的套接字上不断地接收数据。 我
我是一名优秀的程序员,十分优秀!