gpt4 book ai didi

multithreading - 为什么不使用SendMessage()从其他线程访问UI控件的原因?

转载 作者:行者123 更新时间:2023-12-03 13:14:36 32 4
gpt4 key购买 nike

我已经读过SendMessage()不应该用于从其他线程访问UI控件,但是我不确定为什么,我能想到的唯一原因是SendMessage()是一个阻塞调用,那么它可能会导致死锁在某些情况下。

但这是不使用它的唯一原因吗?

编辑:article讨论了不使用SendMessage()的原因,但我认为它不是很清楚(适用于.NET)。

最佳答案

最好记住,编写正确代码的几率不是很高。通用建议是不要这样做!从来没有必要,Windows中GUI程序的UI线程是完全结构化的,以使其易于运行在另一个线程或进程内的代码影响程序的UI。消息循环的关键点,是producer-consumer problem的通用解决方案。 PostMessage()是您利用它的武器。

无论如何,在继续前进之前,首先要考虑一个简单的问题,当您使用SendMessage时很难解决。如何安全正确地关闭 window ?

可以肯定的是,您需要关闭窗口的确切时间完全是不可预测的,并且与工作线程的执行完全不同步。是用户关闭它,或要求UI线程终止,您需要确保该线程已退出并停止调用SendMessage,然后才能真正关闭窗口。

做到这一点的直观方法是在WM_CLOSE消息处理程序中发信号通知事件,要求线程停止。并等待它完成,然后窗口可以关闭。直观,但不起作用,它将使程序死锁。有时,并非总是如此,很难调试。当线程由于被卡在SendMessage调用中而无法检查事件时,将出错。由于UI线程正在等待线程退出,因此无法完成。工作线程无法继续,UI线程无法继续。一个“致命的拥抱”,您的程序将挂起,需要被强行杀死。死锁是一个标准的线程错误。

您会大喊:“我将使用SendMessageTimeout!”但是,您为uTimeout参数传递了什么,以及如何解释ERROR_TIMEOUT错误? UI线程出现故障是很常见的,肯定您之前已经看过“幽灵窗口”,即在标题栏中显示“Not Responding”的窗口。因此,除非您使uTimeout很大,否则ERROR_TIMEOUT不能可靠地指示UI线程正在尝试关闭。至少10秒。这种方法行得通,但是在导出处偶尔出现10秒的挂起并不是一件很漂亮的事情。

解决所有邮件(不仅是WM_CLOSE)的此类问题。接下来应该是WM_PAINT,这是非常非常难以解决的另一个问题。您的工作线程要求在UI线程调用EndPaint()之前的一毫秒内更新显示。因此,从不显示更新,它只会丢失。线程竞赛,另一个标准的线程错误。

第三个经典的线程错误是一个消防水带问题。当工作线程产生结果的速度快于UI线程处理结果的速度时,就会发生这种情况。非常普遍,UI更新非常昂贵。易于检测,很难解决,并且在发生时无法预测。由于您的UI会冻结,因此易于检测,UI线程消耗了100%的内核,试图跟上消息速率。它不再绕过低优先级的任务。喜欢画画。当您使用SendMessage或PostMessage时都会出错。在后一种情况下,您将填满消息队列。包含10000条未处理的消息后,它开始失败。

长话短说,是的,SendMessage()是线程安全的。但是线程安全性不是可传递的属性,它不会自动使您自己的代码成为线程安全的。使用线程时,您仍然会遭受所有可能出错的问题的折磨。僵局,种族,火灾。害怕线程的野兽。

关于multithreading - 为什么不使用SendMessage()从其他线程访问UI控件的原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29580167/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com