我如何在事件调度线程上运行类的所有方法

问题描述 投票:1回答:7

我创建了一个具有几种方法的Swing组件。我希望此类的所有方法都在Swing事件调度线程(EDT)上运行,而调用方在Worker线程上。我目前唯一想到的解决方案是:

对于此类中的每个方法:

public void a(params)

我应该将其重命名为:

private void aOnEDT(params)

并添加另一种方法:

public void a(params) {
    SwingUtilities.invokeAndWait(new Runnable(){
        public void run() {
            aOnEDT(params);
        }
    });
}

但是不是很讨厌吗?我应该怎么做?

java swing event-dispatch-thread
7个回答
2
投票

您可以测试当前是否正在EDT上拨打电话,如果没有,将Runnable放到SwingUtilites.invokeLater()中:

public void myMethod() {
       if (SwingUtilities.isEventDispatchThread()) {
            //... your code
       } else {
           SwingUtilities.invokeLater(
                  new Runnable(){
                     public void run() {
                           myMethod();
                     }
                  });
       {
  }                   

如果您在EDT上,则该方法将保持运行状态,而不会将其置于事件队列的末尾。


1
投票

[只要您想在事件调度线程上执行某些操作,就应该使用SwingUtilities.invokeLater(Runnable doRun)

摘自Javadoc:

导致doRun.run()被执行在AWT事件上异步调度线程。这会发生在所有未决的AWT事件发生之后处理。应该使用这种方法当应用程序线程需要更新GUI。


1
投票

在您需要在EDT上运行的所有方法中,应将方法主体包装在以下代码中:

SwingUtilities.invokeLater(Runnable doRun)

这将使方法中的所有内容都在EDT上运行。因为您正在EDT上运行代码,所以您不应做任何会长时间阻塞的事情。 (文件IO,冗长的计算等)否则,您的GUI将冻结并变得无响应。

SwingUtilities.invokeLater(new Runnable(){public void run(){ // All code placed in here will be ran asynchronously on the EDT }});


0
投票

使用invokeLater() javadocs,并在done()方法中更新您的GUI组件。在donInBackground()方法中进行后台工作。


0
投票

我们完成此工作的一种方法是使用AspectJ。在编译过程中将样板代码注入到所有用@OnEDT注释的方法中。结果代码很苗条,非常方便。

显然,我们必须为此创建注释,切入点和方面,但这几乎是微不足道的。

如果您感兴趣,这里有几个相关链接:

invokeLater()

SwingWorker

http://www.eclipse.org/aspectj/


0
投票

感谢您的所有回复。最后,我们(好吧,只是我的朋友而不是我!)围绕我们的组件创建了一个包装器类。该包装器接收所有调用,创建一个可运行对象(在我们称为实际方法的run()内部),然后将此可运行对象发送给invokeLater()。使用反射库,所有这些似乎并不那么复杂。起点是java.lang.reflect.Proxy类,该类动态创建接口的实例。


0
投票

为了避免类的每个方法中都存在“麻烦”,如果您的类实现了公共接口,则可以使用http://www.eclipse.org/ajdt/EclipseCon2006/来执行与实现方法本身分开的通用http://www.cs.wustl.edu/~mdeters/doc/slides/aspectjtutorial.pdf设置。

  1. 实施一个代理Proxy,该代理将处理所有样板代码以检查事件分配线程并调用Proxy
  2. 创建代理实例并在其上调用方法,而不是直接在您的实现类上。

由于此方法预先包含了更多的代码,因此,仅当您的实现类具有大量要确保在EDT上运行的方法时,它才真正合适。

完整示例:

invokeAndWait

这是使用代理的方式:

InvocationHandler
© www.soinside.com 2019 - 2024. All rights reserved.