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