我有一个观察者类和一个订阅者类。
出于测试目的,观察者创建了一个生成虚假消息和调用的线程,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() 方法中看到了奇怪的崩溃:
它看起来像这样:
调试错误!
程序:c:\myprogram.exe
模块:
文件:i386\chkesp.c
行:42ESP 的值未在函数调用中正确保存。这通常是调用使用一种调用约定声明的函数和使用另一种调用约定声明的函数指针的结果。
我检查了 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 指针。