我在Windows 7 64位(Service Pack 1)上有一个GUI应用程序 我的GUI应用程序中有一些Java,它调度Delphi代码 -
最近,在升级到多核PC之后 - 我们注意到一些繁重的GUI操作会导致GUI卡住。我们只有一个线程可以更新我们的GUI。
调试之后,我们注意到,偶尔会有一个delphi打电话来赢取api的“SendMessage”等等。
然后我们尝试将程序的亲和力设置为1 - 问题解决了,但它减慢了我们的应用程序。
我知道将SendMessage替换为PostMessage或SendMessageTimeout是很常见的,但是我们使用SendMessage +的地方很多,我们也使用也使用SendMessage的DevExpress组件 - 我们不可能映射所有这些地方。
最奇怪的是,即使我们的GUI有一个线程,将亲和度设置为1也可以解决问题(系统中还有其他后台线程,但它们都是纯java并执行一些数据计算)。
我的问题是:
解决此问题的任何已知方法?也许已知Windows 7中的错误?
我发送的邮件是否有可能丢失?总消息或速率是否有限制?如果是这样,我怎样才能增加这些限制?
如何获取更多信息 - 例如:在Windows中的某处检查我的消息发生了什么 - 在哪里/为什么窗户卡住等等 任何进一步分析问题的方法将不胜感激。
非常感谢
答案 0 :(得分:7)
SendMessage()
依赖于目标窗口的消息队列。这是记录在案的行为:
http://msdn.microsoft.com/en-us/library/ms644950.aspx
如果指定的窗口是由其他线程创建的,则系统切换到该线程并调用相应的窗口过程。仅当接收线程执行消息检索代码时才处理线程之间发送的消息。发送线程被阻塞,直到接收线程处理该消息。
因此,SendMessage()
将不会退出,直到目标线程从其消息队列中检索到消息,然后完整地处理消息或调用ReplyMessage()
以释放SendMessage()
,同时继续处理消息。
因此,如果SendMessage()
被卡住,则意味着目标线程没有处理其消息队列,这很好地表明目标线程可能已经死锁,等待其他事情。
当您的应用程序在锁定到1个CPU内核时运行正常但在允许在多个CPU内核上运行时出现问题意味着您的应用可能无法以多核安全方式执行线程间同步。在单核系统中,任何给定时刻只能有一个线程可以物理运行。由于操作系统使用线程调度和任务切换来处理并发的方式,在某些情况下,不安全的同步可能“足够安全”。但是多个内核可以真正并行运行,因此运行在不同内核上的线程可以在同一时刻访问内存/资源,因此正确完成线程间同步以确保不允许这一点非常重要。发生这种情况,否则你的应用程序可能会与自身不同步,并且可能发生各种不良事件(例如 - 你的死锁)。