我的应用程序有需要访问 UI 的后台线程。想象一个国际象棋程序 (AI) 在棋盘上下棋之前“思考”了几秒钟。当线程运行时,UI 被阻止输入,但仍有输出。
涉及3个线程:
- CN1 淡香水
- 思考线程,使用 invokeAndBlock,输出有关搜索过程的信息(在 TextField 中),例如当前移动、搜索深度和搜索值
- 一个时钟线程,以 Thread.start() 开始,每秒更新一次 White 或 Black (TextFields) 使用的时间
在搜索(invokeAndBlock)期间,可以访问 stopButton 以强制停止搜索(未显示)。
下面是我目前的实现。它有效,我的问题是:这是实现它的正确方法吗?
(我阅读了https://www.codenameone.com/blog/callserially-the-edt-invokeandblock-part-1.html和第 2 部分。)
Form mainForm;
TextField whiteTime, blackTime; // updated by clock thread
TextField searchInfo; // updated by think thread
Clock clock;
Move move;
public void start() {
...
mainForm = new Form(...);
...
thinkButton.addActionListener((ActionListener) (ActionEvent evt) -> {
think();
});
mainForm.show();
}
void think() {
blockUI(); // disable buttons except stopButton
clock.start(board.player); // this thread calls showWhiteTime or showBlackTime every second
invokeAndBlock(() -> { // off the EDT
move = search(board, time); // e.g. for 10 seconds
});
clock.stop();
animateMove(board, move);
clock.start(board.player);
freeUI();
}
// search for a move to play
Move search(Board board, int time) {
...
while (time > 0) {
...
showSearchInfo(info); // called say a few times per second
}
return move;
}
void showSearchInfo(String s) { // access UI off the EDT
callSerially(() -> { // callSerially is necessary here
searchInfo.setText(s);
});
}
void showWhiteTime(String s) {
whiteTime.setText(s); // no callSerially needed, although off the EDT (?)
}
void showBlackTime(String s) {
blackTime.setText(s); // no callSerially needed, although off the EDT (?)
}
编辑:think、showWhiteTime 和 showBlackTime 的新版本。
// version 2, replaced invokeAndBlock by Thread.start() and callSerially
void think() {
blockUI(); // disable buttons except stopButton
new Thread(() -> { // off the EDT
clock.start(board.player); // this thread calls showWhiteTime or showBlackTime every second
move = search(board, time); // e.g. for 10 seconds
clock.stop();
callSerially(() -> {
animateMove(board, move);
clock.start(board.player);
freeUI();
});
}).start();
}
// version 2, added callSerially
void showWhiteTime(String s) { // access UI off the EDT
callSerially(() -> {
whiteTime.setText(s);
});
}
// version 2, added callSerially
void showBlackTime(String s) { // access UI off the EDT
callSerially(() -> {
blackTime.setText(s);
});
}