【问题标题】:How to avoid Thread.sleep() in a for loop from interrupting the UI Thread?如何避免 for 循环中的 Thread.sleep() 中断 UI 线程?
【发布时间】:2015-12-09 23:09:04
【问题描述】:

我有以下伪代码来澄清我的问题和解决方案。我的原始帖子和详细结果在 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

问题:正如另一篇文章中详细描述的那样。每个pixelArtFile 将正确显示setTitle() 并暂停约5 秒,但在5 秒过去后,除了最后一个文件外,圆圈不会更改为指定的颜色。就像 TimeUnits.SECONDS.sleep(5); 中的所有代码一样。被跳过除了window.setTitle(...)?

我的理解是 TimeUnits.SECONDS.sleep(5); 中断 UI 线程无法控制,我想必须以某种方式隔离以允许 displayFiles(File pixelArtFile) 完全执行。

您能否向我展示使用伪代码解决此问题的最直接方法,以获得更完整的解决方案?

我尝试过RunnablesPlatform.runLater()FutureTask&lt;Void&gt; 等,但我对它们的工作原理和精确编码感到非常困惑。

我还在网上发布了两个 UI 窗口:Virtual Art。我认为 Pixel Array 窗口中显示的 pixelArtFile 可能会澄清问题。

谢谢

【问题讨论】:

  • 伪代码或代码 sn-ps 很少适合在诸如此类的 StackOverflow 问题中使用。通常对您和预期答案最有帮助的是包括:a)complete, compilable, standalone, minimal code,有人可以复制和粘贴以重现手头的问题(并且仅是问题),b)您的目标的英文描述,c)用英文描述您遇到的问题。
  • 最好在 GitHub 上发布 MCVE 吗?
  • 不,最好在问题中包含 mcve。 MCVE 总是足够小,无需任何额外的外部资源即可放入问题中。

标签: javafx-8 thread-sleep


【解决方案1】:

不要让 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&lt;ModelData&gt; 其中ModelData 是您从a 读取的数据的某个类文件。这样您就不会在动画循环中连续运行 IO。对于每帧 5 秒的动画,这可能并不重要。但是,对于更频繁的动画,这样的优化非常重要。

【讨论】:

  • 感谢 Jewelsea 提供的详细解决方案,解决了我的问题。如果没有提供的关卡细节,我仍然会挣扎。
猜你喜欢
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多