相关疑难解决方法(0)

如何实现Win32 API GetMessage()的"阻塞"行为?

根据这里,GetMessage()是一个阻塞调用,直到可以从消息队列中检索到消息时才会返回.

那么,这种阻止行为是如何实现的呢?

是否GetMessage()使用某种自旋锁,以便UI线程只是忙等待消息队列中出现的新消息?如果是这样,我想至少有一个CPU核心应该在UI应用程序运行时具有很高的使用率.但我没有看到这种情况发生.那么它是怎样工作的?

添加1

感谢评论中的提示.自旋锁意味着降低线程上下文切换的成本.它不应该在这里使用.我也想过这里可能会使用一些事件范例.但如果它是事件驱动的,那么这个事件模型是如何工作的?

我的猜测是这样的:

  • 定期引发输入检查事件.也许通过一些硬件定时器中断.然后定时器中断处理程序将检查输入事件的各种输入设备缓冲区.然后根据当前桌面上下文将其放入某个应用程序的消息队列中,例如哪个是活动窗口.

我想其他一些东西也可能基于定时器中断,例如线程上下文切换.

添加2

根据目前为止的答复.UI线程等待一些事件对象.但是由于UI线程在等待某些东西,它不活跃,并且它本身无法做任何事情.事件对象只是一些被动状态信息.因此,必须有其他人在事件状态更改时唤醒线程.我认为它应该是线程调度程序.并且线程调度可以由定时器中断脉冲.

线程调度程序将定期检查事件状态并唤醒线程并根据需要将消息放入其队列中.

我对整个情况是否正确?

添加3

还有一个问题是:谁修改了事件对象的状态?基于此处,事件似乎只是一些可由任何活动修改的数据结构.我认为线程调度程序只是使用线程和事件之间的关系来决定运行哪个线程.

当一个线程被安排运行时,它的所有要求都应该已经完成​​.诸如消息应该它等待的事件被引发之前被放入其队列中.这是合理的,否则可能为时已晚.(感谢RbMm的评论.)

添加4

在JDK中,LinkedBlockingDeque类型也为该take()方法提供了类似的阻塞行为.

检索并删除此双端队列表示的队列的头部(换句话说,此双端队列的第一个元素),必要时等待,直到元素可用.

.NET对应的是BlockingCollection <T>类型.一个讨论它的线程.

这是一个关于如何在C#中实现阻塞队列的线程.

winapi message-queue win32gui

1
推荐指数
1
解决办法
693
查看次数

为什么Monitor类保留2个队列:“就绪”和“等待”?

根据MSDN

Monitor 类由静态(在 C# 中)或共享(在 Visual Basic 中)方法组成,这些方法对控制对关键部分的访问的对象进行操作。为每个同步对象维护以下信息:

  • 对当前持有锁的线程的引用。

  • 对就绪队列的引用,其中包含准备获取锁的线程。

  • 对等待队列的引用,其中包含正在等待锁定对象状态更改通知的线程。

在这个线程中,两个队列引起了一些微妙的问题。

我认为上述线程中问题的根本原因是有 2 个队列。如果只有一个队列,则无论何时Monitor.Pulse(),都只能调度该队列中的一个线程来运行。没有办法让多个线程同时处于就绪状态。所以这个问题永远不应该发生。

那么为什么a要Monitor保留2个队列呢?

c# queue multithreading

-1
推荐指数
1
解决办法
362
查看次数

标签 统计

c# ×1

message-queue ×1

multithreading ×1

queue ×1

win32gui ×1

winapi ×1