是否可以在 ZK 的桌面范围事件队列中进行服务器推送?

Is it possible to do server push in a desktop-scope event queue in ZK?

我对 ZK 和事件队列的概念还很陌生。我想做的是 运行 在服务器中进行长时间操作并实时更新 UI 进度,而不是在长时间操作 [=] 时阻塞 UI 33=]秒。因此,例如,如果在长操作中有 3 个任务(这个数字不固定)要做,它应该通过更新 "log trace" 文本框和进度条相同次数来更新 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 线程将能够在它们发生时立即处理它们。因此,经过几个小时的反复试验,并注意到桌面范围队列中未使用服务器推送后,我将范围更改为应用程序并明确启用服务器推送:

EventQueue<Event> eq = EventQueues.lookup("longop", EventQueues.APPLICATION, true);
desktop.enableServerPush(true);

刚刚好。我知道 ZK CE 只有客户端轮询,这对我的用例来说很好。但是为什么在桌面范围内,没有使用服务器推送呢?如果我们不想在整个应用程序范围内共享队列,我们​​如何才能完成这样的任务呢?我希望每个桌面都有自己的事件队列。

可能还值得一提的是,我启用了事件线程。而且我尝试禁用它,但结果是一样的。所以在我看来,它不会影响我的问题。

非常感谢任何帮助。

PS: 我正在使用 ZK CE 7.0.3

针对您的情况有多种可能的解决方案。

请看this section of ZK documents

你可以使用 piggyback,但是当用户什么都不做时,你的屏幕也没有更新。

所以我建议去 echoEvents

因此您必须执行任务 1,更新屏幕并回显 onTask2
OnTask2 中做你的事情,更新屏幕并回显 onTask3
onTask3 执行任务 3 并更新屏幕。

编辑:

范围不一定是应用程序范围。应用程序范围事件队列已经内置了服务器推送(我相信会话也是如此)。对于桌面,您必须手动(或其他方法)进行操作。 (应用范围不需要您的 desktop.enableServerPush

如果你想简单地使用事件队列look here.
使用 EventQueue.subscribe(EventListener, EventListener) 什么是异步和同步事件监听器。 唯一的问题是,在同步侦听器中,您需要再次使用同步侦听器调用任务 2 以刷新 GUI 以相同的方式启动任务 3。

另一种方法是将桌面传递给异步侦听器,这样您就可以在那里启用(和禁用)服务器推送。(异步侦听器从不引用桌面,这是一个全新的线程)