У меня есть класс Observer и класс подписчика.
В целях тестирования наблюдатель создает поток, который генерирует поддельные сообщения и вызывает 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
Линия: 42
Значение ESP не было правильно
сохраняется через вызов функции. Это
обычно результат вызова
функция объявлена с одним вызовом
соглашение с указателем на функцию
объявлен с другим призванием
условность.
Я проверил указатель функции, который должен иметь AfxBeginThread ():
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID); // AFXWIN.H
static UINT AFX_CDECL MessageGeneratorThread(LPVOID pParam); // My thread function
Для меня это выглядит совместимым, не так ли?
Не знаю, что еще мне нужно искать. Есть идеи?
Я сделал еще одно странное наблюдение, которое может быть связано:
В методе NotifySubscribers
я вызываю IsWindow()
, чтобы проверить, существует ли окно, на которое указывает дескриптор. По-видимому, это так. Но вызов CWnd::FromHandlePermanent()
возвращает нулевой указатель.