简体   繁体   English

使用EDT调度简单事件的必要性

[英]The Necessity of dispatching simple events with the EDT

Before I go on discussing the basic query I would first like to state that I am fully aware of my question being against the standards of the AWT/Swing framework. 在继续讨论基本查询之前,我首先要声明,我完全意识到我的问题与AWT / Swing框架的标准背道而驰。 My query is meant merely as a academic experience and should (hopefully) never be applied to real world applications. 我的询问仅是一种学术经验,不应(希望)永远不会应用于实际应用。

The AWT/Swing framework is built upon a event based model which uses a single thread to dispatch events. AWT / Swing框架基于基于事件的模型,该模型使用单个线程调度事件。 All AWT/Swing related events events must be processed on the Event Dispatcher Thread (EDT) and any custom events that the programmer has programmed must be queued through the functions invokeAndWait() and invokeLater(). 所有与AWT / Swing相关的事件都必须在事件调度程序线程(EDT)上进行处理,并且程序员已编写的任何自定义事件都必须通过函数invokeAndWait()和invokeLater()进行排队。 While this model ensures that the framework never suffers from any sort of thread concurrency issues it gives a big pain to programmers trying to write code around it (search swing issues on stackoverflow... quite a handful). 尽管此模型可以确保该框架永远不会遭受任何类型的线程并发问题,但它给试图围绕该框架编写代码的程序员带来了极大的痛苦(有​​关stackoverflow的搜索摆动问题,数量很少)。

However... Years ago, before I got more familiar with the AWT/Swing model and the EDT I used to write code that violates many many java standards (code that'll make any reasonable programmer recoil in horror). 但是...几年前,在我更熟悉AWT / Swing模型和EDT之前,我曾经写过违反许多Java标准的代码(这种代码会使任何合理的程序员感到恐惧)。 One of these standards I violated was calling methods that updated the GUI through a thread thats not the EDT. 我违反的这些标准之一是调用通过线程而不是EDT更新GUI的方法。 To be precise it was a standard "long" task that resided on a secondary thread which periodically updated a JLabel with the current progress. 准确地说,这是一个标准的“长”任务,该任务驻留在辅助线程上,该线程会根据当前进度定期更新JLabel。 Reviewing the code now I realized that despite the fact that the code directly violated the standard, it worked 100% of the time. 现在查看代码,我意识到尽管代码直接违反了标准,但它100%的时间都有效。 I noticed no flickering, no corruption of text (since it was a JLabel), no random exceptions being thrown and no abnormal GUI behavior. 我注意到没有闪烁,没有文本损坏(因为它是JLabel),没有引发随机异常,也没有异常的GUI行为。 Of course I know from one tiny example, one cannot simply determine the AWT/Swing standards are over-protective or unnecessary. 当然,从一个很小的例子中我知道,不能简单地确定AWT / Swing标准是过度保护的或不必要的。 And with this, my query lies: 因此,我的查询位于:

For simple tasks like updating a JLabel (not even at a constant rate, maybe once or twice a second) is it truly necessary to perform it through the EDT? 对于诸如更新JLabel的简单任务(甚至不是以恒定的速率,可能每秒更新一两次),是否真的有必要通过EDT执行它? And what are the possible implications (apart from being despised by the whole java programming community) of this (I want a list of solid implications, not just "it might cause the EDT to mess up")? (除了被整个Java编程社区鄙视之外)还有什么可能的含义(我想要一个可靠的含义列表,而不仅仅是“它可能导致EDT混乱”)?

Assume a model where only one thread updates the GUI (which is not the EDT) and the updates are infrequent and only update in atomic operations (updating strings, primitive data, etc) is it possible that the program can run free of problems caused by the EDT (I guess this counts as a hack?). 假设有一个模型,其中只有一个线程更新GUI(不是EDT),并且更新很少,并且仅在原子操作(更新字符串,原始数据等)中更新,则程序可能会运行而不会由于EDT(我想这算是骇客吗?)。

As a challenge, I was wondering if its possible anyone can come up with code that demonstrates a violation of the AWT/Swing model by dispatching events from another thread causing obvious and constant (as in I don't have to wait 2 hours for the GUI to flicker for 1 frame) problems? 作为一个挑战,我想知道是否有可能有人通过从另一个线程中分派导致明显且持续的事件来提出证明违反AWT / Swing模型的代码(例如,我不必等待2个小时) GUI闪烁1帧)有问题吗?

And by the way, this might be unrelated but does a new EDT thread spawn for a new JFrame/Window object or do all of them run off the same thread? 顺便说一句,这可能无关紧要,但是会为新的JFrame / Window对象生成新的EDT线程还是它们都在同一线程上运行? I can't imagine a resource-heavy multi-window system all running off one thread. 我无法想象一个资源繁忙的多窗口系统都在一个线程上运行。

NB: I have never seen nor analyzed the source code of the AWT/Swing framework and all my knowledge is based on internet research and personal experience. 注意:我从未见过或分析过AWT / Swing框架的源代码,我的所有知识都是基于互联网研究和个人经验。 If there is any mistake above, please feel free to correct me. 如果上面有任何错误,请随时纠正我。 For those programmers still in shock from my example above, I have updated all my projects to comply to the standard (what a pain). 对于那些仍然对我的上述示例感到震惊的程序员,我已经更新了所有项目以符合标准(这很痛苦)。

An example of where this fails: Set your JLabel to be right-aligned. 失败的一个示例:将JLabel设置为右对齐。 Then drawing requires two steps - measuring the text, in order to calculate the position, and then drawing it. 然后绘图需要两个步骤-测量文本以计算位置,然后绘图。 If you change the text while it is painting (say, due to an animation loop) the text will seem to jump occasionally. 如果在绘画时更改了文本(例如,由于动画循环),则文本似乎偶尔会跳转。

In answer to your other question - there is only one EDT, for all GUI components. 回答另一个问题-所有GUI组件只有一个EDT。

Example of "constant and obvious" change: Suppose the JLabel has HTML content. “恒定且明显”更改的示例:假设JLabel具有HTML内容。 In your background thread, after the text is set and a repaint is fired, a PropertyChange is also fired, which causes the UI delegate to reparse the HTML and set it in a client property (working in the background thread, although the UI assumes it is in the EDT because it is receiving an event). 在您的背景线程中,在设置了文本并触发了重绘之后,还触发了PropertyChange ,这将导致UI委托重新解析HTML并将其设置为客户端属性(在后台线程中工作,尽管UI假定是这样)在EDT中,因为它正在接收事件)。

So now you have a race condition: If the UI repaints the label (in the EDT) before it finishes calculating the HTML view in the background thread, it will paint the old HTML and your label will appear to not update. 因此,现在您遇到了争用条件:如果UI在完成在后台线程中计算HTML视图之前重新绘制了标签(在EDT中),它将绘制旧的HTML,并且您的标签似乎不会更新。

You could say, "Well then, I just won't use HTML in my label." 您可能会说:“那么,我只是不会在标签中使用HTML。” But the point is that situations like this are pervasive in the Swing libraries - a strong assumption is made everywhere that events are passed only on the EDT, and without reading a huge amount of the Swing source you can't guarantee that you won't run into a problem like this. 但要点是,这种情况在Swing库中无处不在-强烈假设每个事件仅在EDT上传递,并且如果不阅读大量的Swing源代码,您将无法保证不会遇到这样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM