根据这里,GetMessage()是一个阻塞调用,直到可以从消息队列中检索到消息时才会返回.
那么,这种阻止行为是如何实现的呢?
是否GetMessage()使用某种自旋锁,以便UI线程只是忙等待消息队列中出现的新消息?如果是这样,我想至少有一个CPU核心应该在UI应用程序运行时具有很高的使用率.但我没有看到这种情况发生.那么它是怎样工作的?
感谢评论中的提示.自旋锁意味着降低线程上下文切换的成本.它不应该在这里使用.我也想过这里可能会使用一些事件范例.但如果它是事件驱动的,那么这个事件模型是如何工作的?
我的猜测是这样的:
我想其他一些东西也可能基于定时器中断,例如线程上下文切换.
根据目前为止的答复.UI线程等待一些事件对象.但是由于UI线程在等待某些东西,它不活跃,并且它本身无法做任何事情.事件对象只是一些被动状态信息.因此,必须有其他人在事件状态更改时唤醒线程.我认为它应该是线程调度程序.并且线程调度器可以由定时器中断脉冲.
线程调度程序将定期检查事件状态并唤醒线程并根据需要将消息放入其队列中.
我对整个情况是否正确?
还有一个问题是:谁修改了事件对象的状态?基于此处,事件似乎只是一些可由任何活动方修改的数据结构.我认为线程调度程序只是使用线程和事件之间的关系来决定运行哪个线程.
当一个线程被安排运行时,它的所有要求都应该已经完成.诸如消息应该在它等待的事件被引发之前被放入其队列中.这是合理的,否则可能为时已晚.(感谢RbMm的评论.)
在JDK中,LinkedBlockingDeque类型也为该take()方法提供了类似的阻塞行为.
检索并删除此双端队列表示的队列的头部(换句话说,此双端队列的第一个元素),必要时等待,直到元素可用.
.NET对应的是BlockingCollection <T>类型.一个讨论它的线程.
这是一个关于如何在C#中实现阻塞队列的线程.
根据MSDN:
Monitor 类由静态(在 C# 中)或共享(在 Visual Basic 中)方法组成,这些方法对控制对关键部分的访问的对象进行操作。为每个同步对象维护以下信息:
对当前持有锁的线程的引用。
对就绪队列的引用,其中包含准备获取锁的线程。
对等待队列的引用,其中包含正在等待锁定对象状态更改通知的线程。
在这个线程中,两个队列引起了一些微妙的问题。
我认为上述线程中问题的根本原因是有 2 个队列。如果只有一个队列,则无论何时Monitor.Pulse(),都只能调度该队列中的一个线程来运行。没有办法让多个线程同时处于就绪状态。所以这个问题永远不应该发生。
那么为什么a要Monitor保留2个队列呢?