简体   繁体   English

组合guava eventbus和AWT Event线程处理的最佳方法

[英]best way to combine guava eventbus and AWT Event thread handling

When you have a asynchronous event bus, and fire events, lets say within the model which get catched in the UI you have probably the following problem: 当你有一个异步事件总线和fire事件时,让我们说在UI中捕获的模型中你可能有以下问题:

The registered handler gets executed in a worker thread, but all UI swing changes need to be executed within the AWT event thread. 已注册的处理程序在工作线程中执行,但所有UI swing更改都需要在AWT事件线程中执行。 This means you need to envelope all your handler clode in EventQueue.invokeLater(...) . 这意味着您需要在EventQueue.invokeLater(...)包含所有处理程序clode。

This looks like a lot of boiler plate code. 这看起来像很多锅炉板代码。 I wonder if there is a smarter solution for that problem. 我想知道是否有更智能的解决方案来解决这个问题。

What about an extension to the guava event bus that marks a handler for execution within a special thread? guava事件总线的扩展如何标记在特殊线程中执行的处理程序? This could be marked with a annotion eg @ExecuteWithinEDT : 这可以用annotion标记,例如@ExecuteWithinEDT

class EventBusChangeRecorder {
  @Subscribe @ExecuteWithinEDT void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }
}

The handlers registered with an async event bus are executed on whatever thread the provided Executor chooses to run them on, not necessarily a worker thread. 使用异步事件总线注册的处理程序在提供的Executor选择运行它们的任何线程上Executor ,而不一定是工作线程。

What I've done is created an implementation of Executor that runs stuff on the event queue thread. 我所做的是创建了一个Executor的实现,它在事件队列线程上运行东西。 It's pretty simple: 这很简单:

public class EventQueueExecutor implements Executor {
  @Override public void execute(Runnable command) {
    EventQueue.invokeLater(command);
  }
}

You can then just create your EventBus with that: 然后,您可以使用以下方法创建EventBus

EventBus eventBus = new AsyncEventBus(new EventQueueExecutor());

Then all handlers will be executed on the event queue thread. 然后所有处理程序将在事件队列线程上执行。

Edit: 编辑:

An example of forwarding events: 转发事件的示例:

public class EventForwarder {
  private final EventBus uiEventBus;

  public EventForwarder(EventBus uiEventBus) {
    this.uiEventBus = uiEventBus;
  }

  // forward all events
  @Subscribe
  public void forwardEvent(Object event) {
    uiEventBus.post(event);
  }

  // or if you only want a specific type of event forwarded
  @Subscribe
  public void forwardEvent(UiEvent event) {
    uiEventBus.post(event);
  }
}

Just subscribe that to your main event bus and post all events to the main event bus, but subscribe all UI components to the UI event bus. 只需订阅您的主事件总线并将所有事件发布到主事件总线,但是将所有UI组件订阅到UI事件总线。

You can create an EventBus that dispatches only on the AWT thread: 您可以创建仅在AWT线程上调度的EventBus:

EventBus mybus = new AsyncEventBus("awt",
    new Executor() {
        public void execute (Runnable cmd) {
            if (EventQueue.isDispatchThread()) {
                cmd.run();
            } else {
                EventQueue.invokeLater(cmd);
            }
        }
    });

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

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