滚动条消息阻塞 MFC 中的线程间消息
Scrollbar messages block interthread messages in MFC
我有一个由多个线程组成的 MFC 应用程序,但问题出在特定的两个线程上。
- 第一个线程(CGuiThread)负责GUI(它不是主线程)并且包含一个window对象(CMainWindow),它包含一个内部window对象(CInnerWindow),它显示多个进度显示并有一个滚动条。
- 第二个线程(CStatusDispatcherThread)负责向gui线程发送消息,其中包含一些计算过程相关的进度状态信息。
计算开始后,状态调度程序会将包含状态的消息发送到 GUI 线程。 gui 线程相应地更新内部 window 中的进度条。
当我移动或按住内部 window 滚动条的拇指时,问题开始了 - 似乎 GUI 线程停止处理来自状态调度程序线程的状态消息,因为进度条没有更新时间更长。不仅如此,我希望状态消息在某处停止并在我释放 tumb 后进行处理,但它没有发生。新消息到达,但点击时的消息丢失。
如果有人知道可能是什么原因,我将不胜感激。
我尝试了 "catching" CGuiThread::PreaTranslateMessage 函数中的状态消息,但似乎在按住滚动拇指后,它们不再到达那里,即使 CStatusDispatcherThread 的 PostThreadMessage 指示它们已成功发送.
#define MY_MESSAGE 1
class CStatusDispatcherThread : public CWinThread
{
//...
// This class sends progress status percentaget to gui thread via PostThreadMessage
OnTimer(UINT nIDEvent)
{
PostThreadMessage(iThreadID,MY_MESSAGE,100,0);
}
};
class CGuiThread : public CWinThread
{
//...
BEGIN_MESSAGE_MAP(CGuiThread, CWinThread)
ON_THREAD_MESSAGE(MY_MESSAGE,OnStatusMessage)
END_MESSAGE_MAP()
private:
CMyMainWindow m_mainWindow;
void OnStatusMessage(WPARAM iStatus, LPARAM dummy);
{
m_mainWindow.updateStatus((int)iStatus)
}
};
class CMyMainWindow : public CWnd
{
//...
void updateStatus(int iStatus)
{
m_sbarWindow.updateStatusBar(iStatus);
}
private:
CInnerWindow m_sbarWindow;
};
class CInnerWindow : public CWnd
{
//...
void updateStatusBar(int iStatus)
{
//...
}
private:
BOOL Create(...)
{
CWnd::Create(strClassName, strWindowTitle, WS_DLGFRAME | WS_CHILD| WS_VISIBLE | WS_VSCROLL,
rectRectOfWnd, pParentWnd, iID, NULL);
}
void OnVScroll(nSBCode, nPos, pScrollBar)
{
//...
}
};
提前致谢,
加尔
唯一允许更新 GUI 的线程是主线程。否则你最终会遇到意想不到的行为。
记录失败。来自 PostThreadMessage 的 MSDN 页面:
if the recipient thread is in a modal loop (as used by MessageBox or
DialogBox), the messages will be lost.
按住滚动滑块创建这样一个模态循环。您可以通过发布到 HWND 而不是线程 ID 来消除问题。
我有一个由多个线程组成的 MFC 应用程序,但问题出在特定的两个线程上。
- 第一个线程(CGuiThread)负责GUI(它不是主线程)并且包含一个window对象(CMainWindow),它包含一个内部window对象(CInnerWindow),它显示多个进度显示并有一个滚动条。
- 第二个线程(CStatusDispatcherThread)负责向gui线程发送消息,其中包含一些计算过程相关的进度状态信息。
计算开始后,状态调度程序会将包含状态的消息发送到 GUI 线程。 gui 线程相应地更新内部 window 中的进度条。
当我移动或按住内部 window 滚动条的拇指时,问题开始了 - 似乎 GUI 线程停止处理来自状态调度程序线程的状态消息,因为进度条没有更新时间更长。不仅如此,我希望状态消息在某处停止并在我释放 tumb 后进行处理,但它没有发生。新消息到达,但点击时的消息丢失。
如果有人知道可能是什么原因,我将不胜感激。
我尝试了 "catching" CGuiThread::PreaTranslateMessage 函数中的状态消息,但似乎在按住滚动拇指后,它们不再到达那里,即使 CStatusDispatcherThread 的 PostThreadMessage 指示它们已成功发送.
#define MY_MESSAGE 1
class CStatusDispatcherThread : public CWinThread
{
//...
// This class sends progress status percentaget to gui thread via PostThreadMessage
OnTimer(UINT nIDEvent)
{
PostThreadMessage(iThreadID,MY_MESSAGE,100,0);
}
};
class CGuiThread : public CWinThread
{
//...
BEGIN_MESSAGE_MAP(CGuiThread, CWinThread)
ON_THREAD_MESSAGE(MY_MESSAGE,OnStatusMessage)
END_MESSAGE_MAP()
private:
CMyMainWindow m_mainWindow;
void OnStatusMessage(WPARAM iStatus, LPARAM dummy);
{
m_mainWindow.updateStatus((int)iStatus)
}
};
class CMyMainWindow : public CWnd
{
//...
void updateStatus(int iStatus)
{
m_sbarWindow.updateStatusBar(iStatus);
}
private:
CInnerWindow m_sbarWindow;
};
class CInnerWindow : public CWnd
{
//...
void updateStatusBar(int iStatus)
{
//...
}
private:
BOOL Create(...)
{
CWnd::Create(strClassName, strWindowTitle, WS_DLGFRAME | WS_CHILD| WS_VISIBLE | WS_VSCROLL,
rectRectOfWnd, pParentWnd, iID, NULL);
}
void OnVScroll(nSBCode, nPos, pScrollBar)
{
//...
}
};
提前致谢, 加尔
唯一允许更新 GUI 的线程是主线程。否则你最终会遇到意想不到的行为。
记录失败。来自 PostThreadMessage 的 MSDN 页面:
if the recipient thread is in a modal loop (as used by MessageBox or DialogBox), the messages will be lost.
按住滚动滑块创建这样一个模态循环。您可以通过发布到 HWND 而不是线程 ID 来消除问题。