Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.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
User interface Application.DoEvents是否向单独的线程发送消息?_User Interface_Windows Messages_Event Loop - Fatal编程技术网

User interface Application.DoEvents是否向单独的线程发送消息?

User interface Application.DoEvents是否向单独的线程发送消息?,user-interface,windows-messages,event-loop,User Interface,Windows Messages,Event Loop,我一直试图从总体上理解事件循环(进展不太顺利),并且我读到windows消息传递循环是单线程的。如果是,Application.DoEvents如何工作?事件循环不是一次处理一条消息,并在处理每条消息/事件时阻塞吗?消息事件循环是否需要存在于与处理Application.DoEvents消息的线程不同的线程上?如果有单独的线程,我们称之为“主”线程的是哪一个?我确信我遗漏了一些非常简单的东西,我只是不知道它是什么。我花了一天的大部分时间来解决这个问题(如果我说的任何事情都是错误的,请评论并让我知

我一直试图从总体上理解事件循环(进展不太顺利),并且我读到windows消息传递循环是单线程的。如果是,Application.DoEvents如何工作?事件循环不是一次处理一条消息,并在处理每条消息/事件时阻塞吗?消息事件循环是否需要存在于与处理Application.DoEvents消息的线程不同的线程上?如果有单独的线程,我们称之为“主”线程的是哪一个?我确信我遗漏了一些非常简单的东西,我只是不知道它是什么。

我花了一天的大部分时间来解决这个问题(如果我说的任何事情都是错误的,请评论并让我知道,这样我就可以纠正它)。实际上,我必须构建一个旧的Win32应用程序,并自己创建消息循环(我是一个非常顽固的SOB)。因此,有一个名为WinMain的函数启动消息循环,如下所示:

while (GetMessage(&msg, NULL, 0, 0))
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
void DoEvents()
{
   MSG msg;
   HACCEL hAccelTable;

   hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_TESTWIN32));

   // Main message loop:
   while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
   {
       if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
       {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
       }
   }
}
GetMessage()的问题是它会一直阻塞,直到消息队列中有消息可用为止。如果运行带窗口的应用程序,只是坐在那里查看窗口(不要导致任何将消息发布到队列的操作),则主线程(创建窗口的线程)将在GetMessage()上暂停。现在,当消息确实被发布时,我们进入while循环(即如果消息未退出,则为0)。DispatchMessage()是这里有趣的函数。此函数最终将导致控件和EventHandler的执行引发(在.NET中)事件。让我困惑的是,如果调用堆栈是GetMessage()/DispatchMessage()/…/EventHandler,Application.DoEvents()如何处理消息?其实很简单。Win32中的DoEvents将如下所示:

while (GetMessage(&msg, NULL, 0, 0))
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
void DoEvents()
{
   MSG msg;
   HACCEL hAccelTable;

   hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_TESTWIN32));

   // Main message loop:
   while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
   {
       if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
       {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
       }
   }
}
因此DoEvents()实际上在初始消息循环的DispatchMessage()内启动另一个循环来处理事件关键的区别在于,我们没有使用GetMessage()来阻止队列中出现消息,而是使用PeekMessage(),它返回0,并在队列中不再有消息时存在循环。

那么,如果我们单击一个按钮两次,然后在该按钮的EventHandler中调用DoEvents()会怎么样?初始事件循环将处理第一次单击并触发事件。在执行EventHandler时,在DoEvents()调用时,将再次触发事件,并再次输入EventHandler(有点像递归调用)。太可怕了

所以最后,所有的事情都发生在一个线程中,DoEvents()实际上会阻塞,直到所有消息都被处理完毕,然后返回。现在我要去睡几天