番石榴eventbus和AWT事件线程处理结合最好的方法 [英] best way to combine guava eventbus and AWT Event thread handling
问题描述
当你有一个异步事件总线,并且触发事件,其中获得在UI擦肩而过,模型中可以说你有可能存在如下问题:
已注册的处理程序获取在辅助线程执行,但所有UI挥杆的改变需要在AWT事件线程中执行。
这意味着你需要在信封所有的处理程序clode EventQueue.invokeLater(...)
。
这貌似很多锅炉板code的。
我不知道是否有该问题的一个更聪明的解决方案。
有关扩展到一个特殊的线程内,标志着执行的处理番石榴事件总线是什么?这可能是标有annotion例如 @ExecuteWithinEDT
:
类EventBusChangeRecorder {
@Subscribe @ExecuteWithinEDT无效recordCustomerChange(的ChangeEvent发送){
recordChange(e.getChange());
}
}
与异步事件总线注册的处理程序在任何线程提供的执行人
选择运行它们执行对,不一定是工作线程。
我所做的创建执行人
,该事件队列的线程上运行的东西的实现。这是pretty简单:
公共类EventQueueExecutor实现执行人{
@覆盖公共无效的execute(Runnable的命令){
EventQueue.invokeLater(命令);
}
}
您可以然后只需创建 EventBus
与
EventBus eventBus =新AsyncEventBus(新EventQueueExecutor());
然后,所有的处理程序将在事件队列线程上执行。
编辑:
将事件转发的一个例子:
公共类EventForwarder {
私人最终EventBus uiEventBus; 公共EventForwarder(EventBus uiEventBus){
this.uiEventBus = uiEventBus;
} //转发所有事件
@订阅
公共无效forwardEvent(对象事件){
uiEventBus.post(事件);
} //或者如果你只希望事件的特定类型的转发
@订阅
公共无效forwardEvent(的UIEvent事件){
uiEventBus.post(事件);
}
}
刚刚订阅了你的主事件总线和发布所有事件到主事件总线,但是订阅所有UI组件的UI事件总线。
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:
The registered handler gets executed in a worker thread, but all UI swing changes need to be executed within the AWT event thread.
This means you need to envelope all your handler clode in EventQueue.invokeLater(...)
.
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? This could be marked with a annotion e.g. @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.
What I've done is created an implementation of Executor
that runs stuff on the event queue thread. 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 = 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.
这篇关于番石榴eventbus和AWT事件线程处理结合最好的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!