从ui-thread显示窗口有时会阻塞主ui-thread

Displaying window from ui-thread sometimes blocks the main ui-thread

本文关键字:ui-thread 显示 窗口      更新时间:2023-10-16

我不是一个MFC专家,绝对不是一个多线程专家,但仍然,我想了解这种奇怪的行为。在某些地方,当我在我的应用程序中创建一个MFC ui线程时,它启动并可以显示一个消息框,没有问题,主ui线程被阻塞。然而,有时如果我创建了一个线程,那么线程的执行就会停止,直到主ui线程再次被阻塞。

当然情况是编造的。主ui线程的阻塞,象征着某种同步,而ui线程的消息框象征着一些更复杂的ui对话框。

这更像是一个理论问题。我主要感兴趣的是为什么会发生这种情况?下面是一个例子:

class MessageBoxThread : public CWinThread
{
    DECLARE_DYNCREATE( MessageBoxThread );
public:
    virtual BOOL InitInstance()
    {
        CWinThread::InitInstance();
        AfxMessageBox(_T("Some text"));
        return TRUE;
    }
};
IMPLEMENT_DYNCREATE( MessageBoxThread , CWinThread );

void testing()
{
    MessageBoxThread* pMessageBoxThread = new MessageBoxThread ();
    pMessageBoxThread->CreateThread();
    Sleep(10000);
    AfxMessageBox(_T("It Worked!"));
}

所以在这个例子中,如果我把"测试"函数放入CWinApp::InitInstance中,它会按预期工作(首先显示"一些文本",然后在10秒后显示"它工作了!")。但是,如果我把它放到应用程序深处的一个随机位置,可能会发生两个消息框在10秒睡眠后同时出现的情况。是什么导致了这种行为?

我不是MFC粉丝,但知道Win32我可以看到发生了什么。说它"深",你可能是指在一些窗口消息处理代码中调用test()函数——这些代码运行在主UI线程上并处理泵送消息。你让UI线程进入睡眠状态在这个例子中类似于消息框或模态对话框所做的。所以,你的消息泵(在CWinApp中实现,我认为)被这个Sleep()阻塞,等待你完成处理响应你的代码执行的消息(不管什么消息)。

好了,我终于找到答案了。当某人创建ui线程时,此人必须初始化m_pmainnd成员,该成员包含ui线程基窗口。如果您没有这样做,框架将使用应用程序提供的主窗口,即主ui线程中的主窗口。由于Sleep()方法阻塞了那个ui线程,所以另一个ui线程只有在主线程未阻塞时才会响应。