【问题标题】:GUI with c++. lagged when i use button带有 c++ 的图形用户界面。当我使用按钮时滞后
【发布时间】:2016-08-15 03:51:30
【问题描述】:

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

 void CDlgWriteEPC::loop()
{
// Do something
}

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



}

【问题讨论】:

  • 这是什么 API?视窗?它有点像 Windows。

标签: c++ multithreading user-interface


【解决方案1】:

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 对话框应用程序,用于搜索文件中的内容。 如果文件很大,则可能需要很长时间并防止阻塞主线程和 收到“窗口没有响应”消息,我们需要在工作线程中执行此操作。我们可能 例如,还想要一个进度条。

首先,我们在现有的对话框类中定义自己的消息,从 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,您应该能够在手册中找到更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 2016-01-30
    相关资源
    最近更新 更多