我有一个观察者类和一个订阅者类。
出于测试目的,观察者创建了一个生成虚假消息并调用 CServerCommandObserver::NotifySubscribers()
的线程,如下所示:
void CServerCommandObserver::NotifySubscribers(const Command cmd, void const * const pData)
{
// Executed in worker thread //
for (Subscribers::const_iterator it = m_subscribers.begin(); it != m_subscribers.end(); ++it)
{
const CServerCommandSubscriber * pSubscriber = *it;
const HWND hWnd = pSubscriber->GetWindowHandle();
if (!IsWindow(hWnd)) { ASSERT(FALSE); continue; }
SendMessage(hWnd, WM_SERVERCOMMAND, cmd, reinterpret_cast<LPARAM>(pData));
}
}
订阅者是 CDialog
的派生类,它也继承自 CServerCommandSubscriber
。
在派生类中,我添加了一个消息映射条目,它将服务器命令路由到订阅者类处理程序。
// Derived dialog class .cpp
ON_REGISTERED_MESSAGE(CServerCommandObserver::WM_SERVERCOMMAND, HandleServerCommand)
// Subscriber base class .cpp
void CServerCommandSubscriber::HandleServerCommand(const WPARAM wParam, const LPARAM lParam)
{
const Command cmd = static_cast<Command>(wParam);
switch (cmd)
{
case something:
OnSomething(SomethingData(lParam)); // Virtual method call
break;
case // ...
};
}
问题是,我在 HandleServerCommand() 方法中看到奇怪的崩溃:
看起来像这样:
Debug Error!
Program: c:\myprogram.exe
Module:
File: i386\chkesp.c
Line: 42The value of ESP was not properly saved across a function call. This is usually the result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
我检查了 AfxBeginThread() 想要拥有的函数指针:
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID); // AFXWIN.H
static UINT AFX_CDECL MessageGeneratorThread(LPVOID pParam); // My thread function
对我来说,这看起来兼容,不是吗?
我不知道,我还需要寻找什么。有什么想法吗?
我做了另一个奇怪的观察,这可能是相关的:
在 NotifySubscribers
方法中,我调用 IsWindow()
来检查句柄指向的窗口是否存在。显然是这样。但是调用 CWnd::FromHandlePermanent()
会返回 NULL 指针。
最佳答案
来自 afxmsg_.h
:
// for Registered Windows messages
#define ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn) \
{ 0xC000, 0, 0, 0, (UINT_PTR)(UINT*)(&nMessageVariable), \
/*implied 'AfxSig_lwl'*/ \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
所以签名是 LRESULT ClassName::FunctionName(WPARAM, LPARAM)
,而你的是 void ClassName::FunctionName(const WPARAM, const LPARAM)
。这不应该编译,至少在 VS2008 下它不会。
CServerCommandSubscriber 类(在头文件中)中的 HandleServerCommand 声明是什么?
关于c++ - 在线程之间发送窗口消息时出现 ESP 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3101771/