C++ 在std::thread中打开MFC对话框

C++ 在std::thread中打开MFC对话框,c++,mfc,dialog,stdthread,C++,Mfc,Dialog,Stdthread,我想显示一个对话框,通知用户应用程序正忙。为了避免阻塞主线程,我考虑使用std::thread来显示对话框。考虑下面的代码: InProcDlg inProcess; std::thread t([ &inProcess ] { inProcess.DoModal(); delete inProcess; }); // wait till process has finished ::PostMessage(inProcess.m_hWnd, WM_USER

我想显示一个对话框,通知用户应用程序正忙。为了避免阻塞主线程,我考虑使用std::thread来显示对话框。考虑下面的代码:

InProcDlg inProcess;
std::thread t([ &inProcess ] {      
    inProcess.DoModal();
    delete inProcess;
});
// wait till process has finished 
::PostMessage(inProcess.m_hWnd, WM_USER + 1, 0, 0);
if (t.joinable()){
    t.join();
}
InProcDlg.cpp

BEGIN_MESSAGE_MAP(InProcDlg, CDialogEx)
  ...
  ON_MESSAGE(WM_USER + 1, &InProcDlg::close)
END_MESSAGE_MAP()

LRESULT InProcDlg::close(WPARAM wParam, LPARAM lParam)
{
  UNREFERENCED_PARAMETER(wParam, lParam);
  EndDialog(1);
  return 0;
}
运行此代码将正确显示对话框。该对话框也已关闭,但未显示主对话框,应用程序挂起在
CreateRunDlgIndirect()
中。尝试介入时,在设置一些断点时,主对话框将再次正确显示。很奇怪。如果有任何建议需要我深入研究,我将非常高兴

在下一步中,我还想通过发送一个指示进程当前状态的整数向用户显示进程

int *percent;
::PostMessage(inProcess.m_hWnd, WM_USER + 2, 0, reinterpret_cast<LPARAM>(percent));
int*百分比;
::PostMessage(inProcess.m_hWnd,WM_USER+2,0,reinterpret_cast(百分比));
在发送或发布消息之前,如何获得对话框已存在的证据?
我正在使用Visual Studio 2013。

我可以想出两种方法:

无模式对话框

用户线程(UI线程)

使用CWinThread创建主UI线程(CWinApp)的兄弟。最重要的是为CWinThread::m_pMainWnd成员分配一个指向对话框的指针。如果对话框是模态的,则在调用DoModal之后立即返回FALSE,对于无模态的,则返回TRUE

class CMainFrame : public CFrameWnd {
    // pointer to thread
    CWinThread* m_pUserThread;
}
起始线程

m_pUserThread = AfxBeginThread(RUNTIME_CLASS(CUserThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );
m_pUserThread->m_bAutoDelete = TRUE;
m_pUserThread->ResumeThread();
头锉**

class CUserThread : public CWinThread
{
    DECLARE_DYNCREATE(CUserThread)
public:
    CUserThread();

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CUserThread)
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
    //}}AFX_VIRTUAL

protected:
    virtual ~CUserThread();
    // Generated message map functions
    //{{AFX_MSG(CUserThread)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    CUserMsg* m_pDlg;
}
源文件

#define DO_MODAL
BOOL CUserThread::InitInstance()
{

    #ifdef DO_MODAL
    // create and assign Modeless dialog
    CUserMsg dlg;
    m_pMainWnd = &m_pDlg;
    dlg.DoModal();
    return FALSE;
    #endif

    #ifdnef DO_MODAL
    // create and assign Modal dialog
    m_pDlg = new CUserMsg();
    m_pDlg->Create( IDD_USER_DLG, AfxGetMainWnd() );
    m_pMainWnd = m_pDlg;
    return TRUE;
    #endif
}

int CUserThread::ExitInstance()
{
    // check for null
    m_pDlg->SendMessage( WM_CLOSE ) ;
    delete m_pDlg;

    return CWinThread::ExitInstance();
}
终止线程

// post quit message to thread
m_pUserThread->PostThreadMessage(WM_QUIT,0,0);

// wait until thread termineates
::WaitForSingleObject(m_pUserThread->m_hThread,INFINITE);
对于这两种方式,我强烈建议将对话框设置为最顶部的窗口:

BOOL CLicenseGenDlg::OnInitDialog() {
    CDialog::OnInitDialog();

    // TODO: Add extra initialization here
    SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST );
    return TRUE;
}

看一看:进程中是否删除
delete甚至编译?在任何情况下,都可以放弃它—这没有意义。相反,这样做更好,而且通常更容易—在主UI线程上显示对话框,在工作线程上运行繁忙处理。您无法在多个线程之间安全地分布窗口层次结构(请参阅)。撇开这一点不谈,
WM_USER
属于窗口类实现。在这种特殊情况下,一些对话框窗口类。如果你想发送应用程序私有消息,你需要使用
WM_APP+x
消息范围。@IInspectable:该链接特别警告跨进程层次结构,并注意到跨线程窗口层次结构更简单,因为跨线程变量共享更容易,而且没有过滤消息。我担心,如中所述,这将不起作用。