我对ZK和事件队列的概念很陌生。我要做的是在服务器上运行长时间的操作,并实时更新进度的UI,而不是在长时间操作运行时阻塞UI。例如,如果在长时间的操作中有3个任务(这个数字不是固定的),它应该通过更新"日志跟踪"文本框和进度条来更新UI。
我的代码结构如下:
if (EventQueues.exists("longop")) {
print("It is busy. Please wait");
return; //busy
}
EventQueue eq = EventQueues.lookup("longop"); //create a queue
String result;
//subscribe async listener to handle long operation
eq.subscribe(new EventListener() {
public void onEvent(Event evt) {
if ("doLongOp".equals(evt.getName())) {
//simulate a long operation
doTask1();
eq.publish(new Event("printStatus", null, "Task1 completed."));
doTask2();
eq.publish(new Event("printStatus", null, "Task2 completed."));
doTask3();
eq.publish(new Event("printStatus", null, "Task3 completed."));
result = "success";
eq.publish(new Event("endLongOp")); //notify it is done
}
}
}, true); //asynchronous
//subscribe a normal listener to show the resul to the browser
eq.subscribe(new EventListener() {
public void onEvent(Event evt) {
if("printStatus".equals(evt.getName())) {
printToTextbox((String)evt.getData()); //appends value to the log textbox
}
if ("endLongOp".equals(evt.getName())) {
print(result); //show the result to the browser
EventQueues.remove("longop");
}
}
}); //synchronous
eq.publish(new Event("doLongOp")); //kick off the long operation
这不起作用。所有的printStatus事件发生在长操作完成之后。唯一修复的是,无论何时长操作运行,UI都不会被阻塞。我假设由于长操作线程是异步的,它仍然会将事件发送到队列,并且同步UI线程将能够在事件发生时立即处理它们。因此,经过几个小时的尝试和错误之后,在注意到服务器推送没有在桌面作用域队列中使用之后,我将作用域更改为application并显式启用服务器推送:
EventQueue<Event> eq = EventQueues.lookup("longop", EventQueues.APPLICATION, true);
desktop.enableServerPush(true);
它只是工作。我知道ZK CE只有客户端轮询,这对于我的用例来说很好。但是为什么在桌面范围内不使用服务器推送呢?如果我们不希望队列在应用程序范围内共享,我们如何完成这样的任务?我希望每个桌面都有自己的事件队列。
还值得一提的是,我已经启用了事件线程。我试过禁用它,但结果还是一样。所以在我看来,这对我的问题没有影响。
感谢您的帮助。
PS:我使用的是ZK CE 7.0.3
针对您的情况,有很多可能的解决方案。
请看这部分ZK文件
你可以使用背带,但是当用户不做任何事情时,你的屏幕上也没有更新。
所以我建议选echoEvents
。
所以你必须执行任务1,更新屏幕并返回onTask2
。
在OnTask2
做你的东西,更新屏幕和onTask3
。
对于onTask3
,执行任务3并更新屏幕。
作用域不一定是应用程序作用域。应用程序范围事件队列已经内置了服务器推送(我相信会话也是)。对于桌面,您必须手动操作(或其他方法)。(您的desktop.enableServerPush
不需要应用程序范围)
如果你想简单地使用eventqueue,请看这里。
使用EventQueue.subscribe(EventListener, EventListener)
什么是async和sync事件监听器。唯一的问题是,在同步侦听器中,您需要再次使用同步侦听器调用Task 2以刷新GUI 和以相同的方式启动Task 3。
另一种方法是将桌面传递给异步侦听器,这样您就可以在那里启用(或禁用)服务器推送。(异步监听器从来没有引用桌面,它是一个完整的新线程)