在我使用的每个GUI库中(Swing,Android,Windows Forms,WPF),这个黄金法则规定,不能从另一个线程(GUI线程除外)访问或修改GUI元素。我想这个规则适用于任何GUI库。违反此规则很可能会导致应用程序崩溃。但是,我最近一直在想,为什么会这样呢?我找不到任何深刻的解释。 那么这条规则的低级解释是什么?
答案 0 :(得分:3)
除非明确设计并构建,否则任何软件都不是线程安全的。
GUI是一个复杂而有状态的野兽,使其线程安全将会非常昂贵。
答案 1 :(得分:1)
这有一个非常简单的原因。通常,UI函数不是线程安全的(因为它们使线程安全会使性能降低)。
答案 2 :(得分:0)
据我所知,这只是不正确:只要正确应用了线程安全技术,Java中的每个对象都可以同时加入。事实是Java Swing对象大部分都没有为多线程做好准备,所以你必须执行外部同步。
有几个实例,你需要多个线程在GUI中进行互操作:游戏,视觉效果,用户事件......
有关GUI和多线程的更多信息: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
答案 3 :(得分:0)
在您列出的内容中,有些可能是现有机制的包装器,因此您必须通过底层GUI框架间接回答这个问题。在多平台GUI框架的情况下,例如Qt,你也将拥有最低的共同点,决定什么是可能的,什么不是。
现在,为什么访问GUI不是线程安全的?在我最熟悉的情况下(win32和X11),访问通常通过发送请求间接执行,有时候等待相应的答案。这通常以原子方式工作,甚至跨越流程边界,因此这不是问题的直接原因。但是,如果从多个线程执行此操作,则可能发生的最坏情况是以不协调的方式修改数据。例如,如果您从两个线程读取,修改和编写相同的小部件,则这些操作可能是交错的,因此实际上只会应用一个线程的修改。
不支持跨线程访问还有其他原因:
errno
线程安全的方法相同。那就是说,我相信Qt和C#(可能还有其他人)实际上支持一些跨线程操作。他们将使用一些(或多或少模糊)魔法,将调用转发到GUI线程并再次将结果转发回调用线程。换句话说,他们试图让程序员更方便地进行必要的线程间通信,同时保持单线程GUI的效率和简单性。这不仅限于GUI处理,而是一般的方法,只对GUI特别重要。