带有 c++ 的图形用户界面.当我使用按钮时滞后



我是 GUI C++新手,正在修改随机器发送给我的代码,我想在单击按钮时进行 while 循环,我尝试了线程,它仍然卡住了。

 void CDlgWriteEPC::loop()
{
// Do something
}
void CDlgWriteEPC::OnBnClickedOk()
{
    std::thread loadingThread(&CDlgWriteEPC::loop, this);
    loadingThread.join();

}

join 会阻止当前线程,直到另一个线程完成,所以这没有帮助。您应该启动工作线程,立即返回和工作线程完成后应该发送某种消息。

示例代码中的函数名称似乎来自 MSVC++ MFC应用程序,因此我们将使用它。

简而言之,Windows GUI 应用程序是事件驱动的,每次事件发生时,都会发生发送WM_MESSAGE。框架接收这些消息并调用相应的函数来处理它。我们可以定义自己的消息和消息处理程序。这样,工作线程可以将此类消息发送到框架,它将调用我们的处理程序函数。

WM_APP被定义为私人用户消息的起点,因此不会有与现有系统消息的任何冲突。

(https://msdn.microsoft.com/en-us/library/windows/desktop/ms644930%28v=vs.85%29.aspx)

因此,假设我们正在构建一个 MFC 对话框应用程序,用于搜索文件中的某些内容。如果文件很大,则可能需要很长时间,并防止阻塞主线程和收到"窗口没有响应"消息,我们需要在工作线程中执行此操作。我们可能会例如,还需要一个进度条。

首先,我们在现有的 dialog 类中定义我们自己的消息,从 WM_APP + 1 开始我们添加处理程序函数,这些函数必须属于以下类型: afx_msg LRESULT (CWnd::*)(WPARAM, LPARAM)

WPARAM 和 LPARAM 是发布消息时传递的参数,您可以使用它们发送自定义数据。在我们的示例中,我们可以使用它们来发送进度条的进度百分比。

(https://msdn.microsoft.com/en-us/library/k35k2bfs.aspx)

 class CMyAppDlg : public CDialogEx
 {
  public:
    //Public so the worker thread class can use these same sames when posting a message.
    enum Messages  
    {
        MSG_ThreadProgress = WM_APP + 1,
        MSG_ThreadDone
    };
  private:
    afx_msg LRESULT OnThreadProgress(WPARAM wParam, LPARAM lParam)
    {
        ProgressBar->SetPos(wParam); //Worker thread posts progress as wParam
    };
    afx_msg LRESULT OnThreadDone(WPARAM wParam, LPARAM lParam)
    {
        //Get result from worker thread class and use it...
    };
 };

然后我们需要将我们的消息和处理程序添加到消息映射中,您应该将它们添加到已经对话框/文档的.cpp文件中的现有消息映射。

BEGIN_MESSAGE_MAP(CMyAppDlg, CDialogEx) 
ON_MESSAGE(MSG_ThreadProgress, &CMyAppDlg::OnThreadProgress)    
ON_MESSAGE(MSG_ThreadDone, &CMyAppDlg::OnThreadDone)            
END_MESSAGE_MAP()

现在我们可以简单地将这些消息发布在我们的工作线程中,框架主线程将处理消息并更新进度条或使用结果:

class ThreadClass
{
  public:
    //Constructor takes a reference to our dialog class because we need the window handle
    //to post a message
    ThreadClass(CMyAppDlg& MyAppDlg) : mMyAppDlg(MyAppDlg) {};
    void operator()() //Thread worker code...
    {
        while (what_we_look_for_not_found)
        {
            int Progress = 0;
            //Search for a while and update progress variable...
            //Post message to dialog asking it to update the progressbar
            PostMessage(mMyAppDlg.m_hWnd, CMyAppDlg::MSG_ThreadProgress, Progress, 0);
        }
        //Finished searching...
        StoreResult();
        //Post message to dialog informing it thread is done and result can be retrieved.
        PostMessage(mMyAppDlg.m_hWnd, CMyAppDlg::MSG_ThreadDone, 0, 0);
    }
  private:
    CMyAppDlg& mMyAppDlg;
};

QT使用与SIGNAL和SLOT类似的系统,其他框架肯定有自己的等效系统。如果您使用的是MSVC++ MFC以外的其他东西,您应该能够在手册中找到更多信息。

最新更新