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



我对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。

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

最新更新