如何避免 for 循环中的 Thread.sleep() 中断 UI 线程?
How to avoid Thread.sleep() in a for loop from interrupting the UI Thread?
我有以下伪代码来阐明我的问题和解决方案。我的原始 posting 和详细结果在 Stack Overflow 上:Wait() & Sleep() Not Working As Thought。
public class PixelArtSlideShow { // called with click of Menu item.
create List<File> of each selected pixelArtFile
for (File pixelArtFile : List<File>) {
call displayFiles(pixelArtFile);
TimeUnits.SECONDS.sleep(5); }
}
public static void displayFiles(File pixelArtFile) {
for (loop array rows)
for (loop array columns)
read-in sRGB for each pixel - Circle Object
window.setTitle(....)
}
// when above code is used to Open a pixelArtFile, it will appear instantly in a 32 x 64 array
问题:正如另一个 post 中所详述的那样。每个 pixelArtFile
都会正确显示 setTitle()
并暂停大约 5 秒,但在 5 秒后,除了最后一个文件外,圆圈不会更改为分配的颜色。就像 TimeUnits.SECONDS.sleep(5) 中的所有代码一样;被跳过除了 window.setTitle(...)
?
我的理解是 TimeUnits.SECONDS.sleep(5);
中断了无法控制的 UI 线程,我想必须以某种方式隔离以允许 displayFiles(File pixelArtFile)
完全执行。
你能告诉我使用伪代码解决这个问题的最直接的方法以获得更完整的解决方案吗?
我已经尝试了 Runnables
、Platform.runLater()
、FutureTask<Void>
等,但我对它们的工作原理和编码方式感到非常困惑。
我也有两个 UI windows post 在网络上编辑:Virtual Art。我认为像素阵列 window 中显示的 pixelArtFile
可能会阐明问题。
谢谢
不要休眠 UI 线程。时间线可能会做你想做的事。
List<File> files;
int curFileIdx = 0;
// prereq, files have been appropriately populated.
public void runAnimation() {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(5), event -> {
if (!files.isEmpty()) {
displayFile(curFileIdx);
curFileIdx = (curFileIdx + 1) % files.size();
}
})
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
// prereq, files have been appropriately populated.
public void displayFile(int idx) {
File fileToDisplay = files.get(idx);
// do your display logic.
}
注意,除了上述之外,你可能还想运行一个单独的task来将文件数据读入内存,并且只需要一个List<ModelData>
where [=12] =] 是一些 class 表示您从文件中读取的数据。这样你就不会在你的动画循环中持续 运行ning IO。对于每帧 5 秒的动画,这可能无关紧要。但是,对于更频繁的动画,这样的优化是非常重要的。
我有以下伪代码来阐明我的问题和解决方案。我的原始 posting 和详细结果在 Stack Overflow 上:Wait() & Sleep() Not Working As Thought。
public class PixelArtSlideShow { // called with click of Menu item.
create List<File> of each selected pixelArtFile
for (File pixelArtFile : List<File>) {
call displayFiles(pixelArtFile);
TimeUnits.SECONDS.sleep(5); }
}
public static void displayFiles(File pixelArtFile) {
for (loop array rows)
for (loop array columns)
read-in sRGB for each pixel - Circle Object
window.setTitle(....)
}
// when above code is used to Open a pixelArtFile, it will appear instantly in a 32 x 64 array
问题:正如另一个 post 中所详述的那样。每个 pixelArtFile
都会正确显示 setTitle()
并暂停大约 5 秒,但在 5 秒后,除了最后一个文件外,圆圈不会更改为分配的颜色。就像 TimeUnits.SECONDS.sleep(5) 中的所有代码一样;被跳过除了 window.setTitle(...)
?
我的理解是 TimeUnits.SECONDS.sleep(5);
中断了无法控制的 UI 线程,我想必须以某种方式隔离以允许 displayFiles(File pixelArtFile)
完全执行。
你能告诉我使用伪代码解决这个问题的最直接的方法以获得更完整的解决方案吗?
我已经尝试了 Runnables
、Platform.runLater()
、FutureTask<Void>
等,但我对它们的工作原理和编码方式感到非常困惑。
我也有两个 UI windows post 在网络上编辑:Virtual Art。我认为像素阵列 window 中显示的 pixelArtFile
可能会阐明问题。
谢谢
不要休眠 UI 线程。时间线可能会做你想做的事。
List<File> files;
int curFileIdx = 0;
// prereq, files have been appropriately populated.
public void runAnimation() {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(5), event -> {
if (!files.isEmpty()) {
displayFile(curFileIdx);
curFileIdx = (curFileIdx + 1) % files.size();
}
})
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
// prereq, files have been appropriately populated.
public void displayFile(int idx) {
File fileToDisplay = files.get(idx);
// do your display logic.
}
注意,除了上述之外,你可能还想运行一个单独的task来将文件数据读入内存,并且只需要一个List<ModelData>
where [=12] =] 是一些 class 表示您从文件中读取的数据。这样你就不会在你的动画循环中持续 运行ning IO。对于每帧 5 秒的动画,这可能无关紧要。但是,对于更频繁的动画,这样的优化是非常重要的。