我在EDT中运行了数百种不同的功能。其中很多包括长期运行的任务,还有一些包括对GUI的更改。有时GUI会挂起用户,但由于GUI挂起不会在100%的时间内在同一区域内发生,因此很难跟踪发生的所有位置。问题不是高优先级,因为挂起通常在最小化/最大化窗口后开始工作,但最终需要完成。
经过一些研究后,我发现我可以在SwingWorker下使用doInBackground()用于任何具有劳动兼性工作的方法,并使用done()进行GUI绘制。另外我相信我可以使用SwingUtilities.invokeLater用于恰好位于doInBackground()函数中的每个GUI绘图。但是,我想避免调整代码中的数百个函数中的每一个。
有没有办法可以使用单个SwingWorker并将任何长时间运行的方法发送到doInBackground()函数?对于使用SwingWorker的每个放错位置的GUI代码,多次使用invokeLater函数不是一个问题,因为它不常见。
如果这不可能,我可以使用某种替代品吗?谢谢。
答案 0 :(得分:2)
必须在EDT上调用更新GUI的所有方法,否则您可能会遇到一些无法解释的GUI行为(听起来就像您所看到的那样)。你可能有不正确的重绘,线程竞赛等。
不建议在GUI上运行长时间运行的任务,因为它们会导致GUI无响应,因此对于长时间运行的任务,SwingWorker是一个很好的解决方案(请注意,进程和完成方法在EDT会自动执行,以便您的工作人员可以在doInBackground中执行长时间运行的工作,但您可以安全地更新GUI,而无需使用完成方法中的SwingUtilities.invokeLater。
正如您所提到的,您有数百种方法,并且您不希望每次都调用SwingUtilities.invokeLater,您可能需要查看其中一个任务框架。 Swing应用程序框架是JSR-296 http://java.sun.com/developer/technicalArticles/javase/swingappfr/下的开发人员,但没有得到积极支持,但仍然提供了一个很好的框架。 http://en.wikipedia.org/wiki/Swing_Application_Framework是备选框架的列表。
听起来您需要在应用程序中进行一些重要的重写。从EDT外部调用GUI方法是不安全的。
答案 1 :(得分:1)
我看不出你的要求是怎样的。在执行之前,Swing无法知道什么是合格的“长时间运行”方法调用。如果该方法已经被执行(在EDT上),Swing不能简单地将其拾取并将其移动到新线程。即使你指出哪些方法调用应该在后台线程中运行,拉掉它也很难。我认为在Java中实现这一目标的唯一方法是使用AOP(您可以拦截方法调用)。但是实施AOP会更难以重新实现现有的应用程序以使用SwingWorkers。
听起来你的Swing应用程序的架构已经崩溃了。不得在EDT上执行长时间运行的任务。对不起,我想你只需要咬紧牙关。如果您希望应用程序感觉活泼,响应迅速且具有可预测的行为,则必须通过将长时间运行的代码放在后台线程中来解决此问题。
如果您的应用程序使用了大量后台任务,您可能希望使用优秀的Swing Task API。否则你会很快发现自己在SwingWorker意大利面条中。
对于恰好位于doInBackground()
中的每个GUI绘图
你不能在'doInBackground()'方法中调用Swing绘图,更新等方法(实际上你可以,但你不能这样做)。这是因为这是从EDT执行的方法。只能在SwingWorker的'done()'方法中调用GUI绘图和组件更新。