2015-08-13 41 views
0

我有两个任务,一个用于更改屏幕不透明度,另一个用于执行复杂计算。我想计算开始后,才在屏幕衰落实际上已经改变了,所以我写了下面的:JavaFX中的并发 - 任务未完成

  Task<Void> task = new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       stage.getScene().getRoot().setOpacity(0.2); 
       stage.show(); 
       return null; 
      } 
     }; 

     Task<Void> task2 = new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       // Complex computation 
       return null; 
      } 
     }; 
     task.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
      @Override 
      public void handle(WorkerStateEvent paramT) { 
       // this busy waiting line was added in attempt to force the 
       // fading before beginning second task 
       while (stage.getScene().getRoot().getOpacity() != 0.2) {} 
       stage.show(); 
       Platform.runLater(task2); 
      } 
     }); 
     task2.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
      @Override 
      public void handle(WorkerStateEvent paramT) { 
       stage.getScene().getRoot().setOpacity(1); 
       stage.show(); 
      } 
     }); 
     task.run(); 

但是,有时我看到的计算开始和屏幕,它的完成后才消失。有时它确实起作用。所以我认为这里有一个线程问题。注意:当我处于调试模式并停止执行每个任务时,它每次都能正常工作。在第二项任务开始之前可以做些什么来强制屏幕褪色?

编辑: 至于建议,我改变了代码如下:

  Task<Void> task1 = new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       // Long computation 
       return null; 
      } 
     }; 

     Task<Void> task = new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       FadeTransition ft = new FadeTransition(Duration.millis(1), stage.getScene().getRoot()); 
       ft.setFromValue(1.0); 
       ft.setToValue(0.1); 
       ft.setCycleCount(1); 
       //ft.setAutoReverse(true); 
       ft.play(); 

       ft.setOnFinished(new EventHandler<ActionEvent>() { 
        @Override 
        public void handle(ActionEvent event) { 
         new Thread(task1).run(); 
        } 
       }); 

       return null; 
      } 
     }; 

     task1.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
      @Override 
      public void handle(WorkerStateEvent paramT) { 
       FadeTransition ft1 = new FadeTransition(new Duration(0.1), stage.getScene().getRoot()); 
       ft1.setFromValue(0.1); 
       ft1.setToValue(1.0); 
       ft1.setCycleCount(1); 
       //ft.setAutoReverse(true); 
       ft1.play(); 
       //stage.show(); 
      } 
     }); 
     new Thread(task).run(); 

我仍然看到相同的行为。

+0

有这么多错在这里很难知道从哪里开始。你的任务都不会在后台线程中执行(第一个,你只需调用'run(...)',它将在当前线程中执行它;在第二个中,你可以用它来执行它FX应用程序线程调用'Platform.runLater(...)')。你的第一个'Task'更新UI,如果你在后台线程中运行,这将是非法的。 'setOpacity(...)'不会像您期望的那样创建“淡入淡出”,但会立即改变不透明度。你的'onSucceeded'阻止执行,这会冻结UI。 –

+0

如果您想要“淡入淡出”,请使用['FadeTransition]](http://docs.oracle.com/javase/8/javafx/api/javafx/animation/FadeTransition.html)。启动淡入转场的'onFinished'处理程序中的第二项任务。这里不需要屏蔽(因为淡入淡出已经完成)。在后台线程中启动执行计算的任务,或将其传递给执行程序。请参阅['任务'Javadocs](http://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html)。 –

回答

0

更换

new Thread(task).run(); 

new Thread(task).start(); 
+0

这不是错误的原因,但仍然是调用start而不是run的好方式。 Findbugs也发现这是一个错误。 – maxam