Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么';t消息框阻止线程?_C++_Multithreading_Winapi - Fatal编程技术网

C++ 为什么';t消息框阻止线程?

C++ 为什么';t消息框阻止线程?,c++,multithreading,winapi,C++,Multithreading,Winapi,考虑下面的代码片段,其中在WM_定时器消息上显示消息框 #define IDT_TIMER1 1001 INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { //... case WM_INITDIALOG: { //... SetTi

考虑下面的代码片段,其中在WM_定时器消息上显示消息框

#define IDT_TIMER1 1001

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch(message) {

        //...

        case WM_INITDIALOG:
        {
            //...

            SetTimer(hWnd, IDT_TIMER1, 1000, (TIMERPROC)NULL);

            break;
        }
        case WM_TIMER:
        {
            int ret = MessageBox(hWnd, L"Cancel operation?", NULL, MB_YESNO);
            if(ret == IDYES) {
                EndDialog(hWnd, 0);
            } else {
                // no-op: keep going
            }

            break;
        }

        //...

        default:
            return FALSE;
    }

    return FALSE;
}
我希望这段代码在初始计时器滴答声时显示一个消息框,并阻止线程,直到用户单击一个按钮。实际发生的情况是,即使用户没有单击任何按钮,在每个计时器滴答声处都会显示一个新建消息框

当我检查线程的调用堆栈时,我看到对
DialogProc()
的多个调用,所有调用
MessageBox()
的调用都停留在行上(即所有调用都等待用户输入)

给定调用堆栈的状态,
DialogProc()
DialogProc()
最后一次调用
DialogProc()
时,
MessageBox()
尚未返回的线程中,如何可能继续被调用
DialogProc()


请注意,我不是在问如何实现所期望的行为。我只是想了解“引擎盖下”到底发生了什么导致了实际的行为。

MessageBox
启动了一个新的,除其他外,它可以通过正常的Windows回调机制访问并调用您的
DialogProc


如果它没有这样做,那么像
WM_PAINT
这样的事件就不会得到处理,你的应用程序看起来就像已经死掉了一样(除了消息框)。由于计时器仍在运行,
WM_timer
事件在适当的时间排队。

MessageBox
进入渲染窗口所需的嵌套消息循环,处理按钮

MessageBox
call中指定为第一个参数的窗口已被
EnableWindow
禁用输入,但这并不会禁用所有消息,因此您仍然会收到WM_PAINT、WM_TIMER和其他消息。通常它会禁用用户输入:鼠标、键盘,但也会使用鼠标调整窗口大小

此伪代码显示了MessageBox模拟的潜在实现方式:

int MessageBox( HWND owner_hwnd, ... )
{
    ...
    HWND box_hwnd = CreateWindowEx( ..., owner_hwnd, ... );
    ...
    EnableWindow( owner_hwnd, FALSE );
    ...
    while ( !done )
    {
        MSG msg;
        GetMessage( &msg, ... );
        if ( IsDialogMessage( box_hwnd, &msg ) )
            continue;
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    ...
    EnableWindow( owner_hwnd, TRUE );
    ...
    DestroyWindow( box_hwnd );
    ...
    return button;
}