Professional Documents
Culture Documents
Cet article a pour but de vous expliquer comment excuter une tche de fond en JavaFX
sans avoir recourir un Thread lance manuellement et sans bloquer l'excution du thread
principal de gestion des vnements.
Pour ragir au contenu de cet article, un espace de dialogue vous est propos sur le forum
Commentez
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
I - Introduction..............................................................................................................................................................3
II - Problmatique........................................................................................................................................................ 3
II-A - Exemple.........................................................................................................................................................3
II-B - Raisonnement............................................................................................................................................... 6
II-C - Solution......................................................................................................................................................... 6
III - Interfaces et classes importantes....................................................................................................................... 10
III-A - javafx.concurrent.Worker<V>..................................................................................................................... 10
III-B - javafx.concurrent.Service<V>.....................................................................................................................10
III-C - javafx.concurrent.Task<V>......................................................................................................................... 11
III-D - Javafx.concurrent.ScheduledService<V>...................................................................................................11
IV - Utiliser un service............................................................................................................................................... 12
IV-A - Cration et lancement............................................................................................................................... 12
IV-B - Annulation.................................................................................................................................................. 12
IV-C - Relancer un service...................................................................................................................................13
IV-D - Avancement du service............................................................................................................................. 13
IV-E - tat du service...........................................................................................................................................13
IV-E-1 - ChangeListener sur l'tat du service................................................................................................ 14
IV-E-2 - Callback sur le service......................................................................................................................15
IV-F - Rcuprer le rsultat................................................................................................................................. 16
IV-G - Rcuprer la raison de l'chec................................................................................................................. 16
V - Utiliser une tche.................................................................................................................................................17
V-A - Notification de l'avancement.......................................................................................................................17
V-B - Annulation................................................................................................................................................... 17
V-B-1 - Lors d'un appel bloquant................................................................................................................... 18
V-C - tat d'une tche......................................................................................................................................... 18
V-D - Produire des rsultats partiels....................................................................................................................19
V-D-1 - JDK 7................................................................................................................................................. 19
V-D-2 - JDK 8................................................................................................................................................. 20
V-E - Utiliser une tche dans un contexte non JavaFX...................................................................................... 21
VI - Utiliser un service rptable...............................................................................................................................21
VI-A - Dlai avant l'excution...............................................................................................................................21
VI-B - Priode d'excution................................................................................................................................... 22
VI-C - Gestion des checs...................................................................................................................................22
VI-D - Derniers bons rsultats............................................................................................................................. 22
VII - Conclusion......................................................................................................................................................... 22
VIII - Remerciements................................................................................................................................................. 22
IX - Liens....................................................................................................................................................................23
-2-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
I - Introduction
Comme dans n'importe quel logiciel, il peut arriver que l'utilisateur soit amen excuter une tche de longue dure
pour par exemple un calcul, charger ou sauvegarder un fichier, effectuer une requte web ou sur une base de donnes
ou encore faire une pause pendant une dure dtermine ou effectuer une boucle infinie pour surveiller l'tat d'un
port, d'un priphrique ou d'un fichier.
Or si on ne prend pas attention la manire dont ces tches longues sont traites, il est trs facile de bloquer le
fonctionnement de l'UI, ce qui laissera penser l'utilisateur que le programme a plant puisque plus rien ne rpond
ses saisies. Fort heureusement, l'API JavaFX fournit via son API de concurrence une interface et une paire de
classes tout spcialement ddies la gestion des tches de fond, ce qui facilite grandement la gestion de ce genre
d'oprations.
II - Problmatique
II-A - Exemple
Prenons un problme simple : nous disposons d'une UI contenant un simple bouton et nous allons lancer le calcul
de 1 000 000 d'entiers lorsque nous cliquons sur ce bouton. Nous allons galement changer le curseur de l'UI et
le remplacer par un curseur d'attente et nous dsactiverons les boutons permettant de lancer le calcul pendant que
ce dernier tourne.
Code JDK7
1. package test;
2.
3. import javafx.application.Application;
4. import javafx.application.Platform;
5. import javafx.event.ActionEvent;
6. import javafx.event.EventHandler;
7. import javafx.scene.Cursor;
8. import javafx.scene.Scene;
9. import javafx.scene.control.Button;
10. import javafx.scene.control.Menu;
11. import javafx.scene.control.MenuBar;
12. import javafx.scene.control.MenuItem;
13. import javafx.scene.layout.BorderPane;
14. import javafx.scene.layout.StackPane;
15. import javafx.stage.Stage;
16.
17. public class Main extends Application {
18.
19.
private MenuItem calculateItem;
20.
private Button calculateButton;
21.
private Scene scene;
22.
23.
@Override
24.
public void start(Stage primaryStage) {
25.
final MenuItem exitItem = new MenuItem("Quitter");
26.
exitItem.setOnAction(new EventHandler<ActionEvent>() {
27.
28.
@Override
29.
public void handle(ActionEvent t) {
30.
Platform.exit();
31.
}
32.
});
final Menu fileMenu = new Menu("Fichier");
33.
fileMenu.getItems().add(exitItem);
34.
calculateItem = new MenuItem("Calculer");
35.
calculateItem.setOnAction(new EventHandler<ActionEvent>() {
36.
37.
@Override
38.
public void handle(ActionEvent t) {
39.
doCalculate();
40.
}
-3-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK7
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83. }
});
final Menu actionMenu = new Menu("Action");
actionMenu.getItems().add(calculateItem);
final MenuBar menuBar = new MenuBar();
menuBar.getMenus().setAll(fileMenu, actionMenu);
calculateButton = new Button();
calculateButton.setText("Lancer le calcul !");
calculateButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
doCalculate();
}
});
StackPane center = new StackPane();
center.getChildren().add(calculateButton);
final BorderPane root = new BorderPane();
root.setTop(menuBar);
root.setCenter(center);
scene = new Scene(root, 300, 250);
primaryStage.setTitle("Test");
primaryStage.setScene(scene);
primaryStage.show();
Code JDK8
1. package test;
2.
3. import javafx.application.Application;
4. import javafx.application.Platform;
5. import javafx.event.ActionEvent;
6. import javafx.scene.Cursor;
7. import javafx.scene.Scene;
8. import javafx.scene.control.Button;
9. import javafx.scene.control.Menu;
10. import javafx.scene.control.MenuBar;
11. import javafx.scene.control.MenuItem;
12. import javafx.scene.layout.BorderPane;
13. import javafx.scene.layout.StackPane;
14. import javafx.stage.Stage;
15.
16. public class Main extends Application {
17.
18.
private MenuItem calculateItem;
19.
private Button calculateButton;
20.
private Scene scene;
21.
22.
@Override
23.
public void start(Stage primaryStage) {
24.
final MenuItem exitItem = new MenuItem("Quitter");
25.
exitItem.setOnAction((ActionEvent t) -> Platform.exit());
-4-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65. }
-5-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Nous pouvons dsormais lancer notre calcul soit en cliquant directement sur le bouton Lancer le calcul !, soit en
allant dans le menu Action -> Calculer.
Lorsque nous dmarrons le calcul, nous pouvons nous rendre compte de plusieurs choses :
C'est bien normal : nous ragissons immdiatement l'action sur le bouton ou le menu et nous excutons notre long
calcul dans le mme thread que celui qui gre l'affichage et les vnements dans l'UI. Cette dernire ne peut donc
plus rafraichir son affichage ni mme ragir nos saisies.
Et souvenez-vous qu'il s'agit ici d'un simple calcul numrique, le problme se pose galement lors de la lecture ou
l'criture de fichiers, d'un accs une base de donnes, sur le rseau ou sur Internet
II-B - Raisonnement
Tout comme Swing et AWT s'excutent dans l'EDT (Event Dispatch Thread), JavaFX utilise des threads qui lui sont
propres tels que le JavaFX Application Thread, le thread de rendu Prism ou encore le thread media. Les vnements
reus via les listeners ou le binding ou encore les appels aux callbacks sont tous excuts dans le JavaFX Application
Thread.
Tout comme dans Swing et AWT, lancer un traitement long dans le thread de gestion des vnements de JavaFX
peut mener un blocage (freeze) de l'UI de l'application qui ne rpond alors plus aux entres de l'utilisateur. Ce
dernier peut alors tre amen penser que l'application est bogue ou plante. Il faut donc excuter ce genre de
traitement en tche de fond (background task) sans bloquer les threads de l'UI.
Bien qu'il soit possible de lancer manuellement un ou plusieurs Thread pour effectuer le traitement, la gestion de la
remonte d'informations vers l'UI (progression, message, remonte des erreurs) peut s'avrer assez complique
programmer. C'est ici qu'intervient l'API de concurrence de JavaFX !
II-C - Solution
Reprenons notre code et utilisons l'API de concurrence de JavaFX. Pour cela, nous allons juste modifier le code
de la mthode doCalculate() ainsi que les imports pour lister les nouvelles classes ncessaires. Nous reviendrons
ultrieurement sur les diverses classes et mcanismes introduits dans ce code :
Code JDK7
1. package test;
2.
3. import javafx.application.Application;
4. import javafx.application.Platform;
5. import javafx.beans.value.ChangeListener;
6. import javafx.beans.value.ObservableValue;
7. import javafx.concurrent.Service;
8. import javafx.concurrent.Task;
9. import javafx.concurrent.Worker;
10. import javafx.event.ActionEvent;
11. import javafx.event.EventHandler;
12. import javafx.scene.Cursor;
13. import javafx.scene.Scene;
14. import javafx.scene.control.Button;
15. import javafx.scene.control.Menu;
16. import javafx.scene.control.MenuBar;
17. import javafx.scene.control.MenuItem;
18. import javafx.scene.layout.BorderPane;
19. import javafx.scene.layout.StackPane;
-6-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK7
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK7
90.
};
91.
}
92.
};
93.
calculateService.stateProperty().addListener(new ChangeListener<Worker.State>() {
94.
95.
@Override
96.
public void changed(ObservableValue<? extends Worker.State> observableValue,
Worker.State oldValue, Worker.State newValue) {
97.
switch (newValue) {
98.
case FAILED:
99.
case CANCELLED:
100.
case SUCCEEDED:
101.
scene.setCursor(oldCursor);
102.
calculateItem.setDisable(false);
103.
calculateButton.setDisable(false);
104.
break;
105.
}
106.
}
107.
});
108.
calculateService.start();
109.
}
110.
111.
public static void main(String[] args) {
112.
launch(args);
113.
}
114. }
Code JDK
1. package test;
2.
3. import javafx.application.Application;
4. import javafx.application.Platform;
5. import javafx.beans.value.ObservableValue;
6. import javafx.concurrent.Service;
7. import javafx.concurrent.Task;
8. import javafx.concurrent.Worker;
9. import javafx.event.ActionEvent;
10. import javafx.scene.Cursor;
11. import javafx.scene.Scene;
12. import javafx.scene.control.Button;
13. import javafx.scene.control.Menu;
14. import javafx.scene.control.MenuBar;
15. import javafx.scene.control.MenuItem;
16. import javafx.scene.layout.BorderPane;
17. import javafx.scene.layout.StackPane;
18. import javafx.stage.Stage;
19.
20. public class Main extends Application {
21.
22.
private MenuItem calculateItem;
23.
private Button calculateButton;
24.
private Scene scene;
25.
26.
@Override
27.
public void start(Stage primaryStage) {
28.
final MenuItem exitItem = new MenuItem("Quitter");
29.
exitItem.setOnAction((ActionEvent t) -> Platform.exit());
30.
final Menu fileMenu = new Menu("Fichier");
31.
fileMenu.getItems().add(exitItem);
32.
calculateItem = new MenuItem("Calculer");
33.
calculateItem.setOnAction((ActionEvent t) -> doCalculate());
34.
final Menu actionMenu = new Menu("Action");
35.
actionMenu.getItems().add(calculateItem);
36.
final MenuBar menuBar = new MenuBar();
37.
menuBar.getMenus().setAll(fileMenu, actionMenu);
38.
calculateButton = new Button();
39.
calculateButton.setText("Lancer le calcul !");
40.
calculateButton.setOnAction((ActionEvent event) -> doCalculate());
41.
StackPane center = new StackPane();
42.
center.getChildren().add(calculateButton);
-8-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK
43.
final BorderPane root = new BorderPane();
44.
root.setTop(menuBar);
45.
root.setCenter(center);
46.
scene = new Scene(root, 300, 250);
47.
primaryStage.setTitle("Test");
48.
primaryStage.setScene(scene);
49.
primaryStage.show();
50.
}
51.
52.
private void doCalculate() {
53.
final Cursor oldCursor = scene.getCursor();
54.
scene.setCursor(Cursor.WAIT);
55.
calculateItem.setDisable(true);
56.
calculateButton.setDisable(true);
57.
final Service<Void> calculateService = new Service<Void>() {
58.
59.
@Override
60.
protected Task<Void> createTask() {
61.
return new Task<Void>() {
62.
63.
@Override
64.
protected Void call() throws Exception {
65.
final int maxIterations = 1000000;
66.
for (int iterations = 0; iterations < maxIterations; iterations ++) {
67.
System.out.println(iterations);
68.
}
69.
return null;
70.
}
71.
};
72.
}
73.
};
74.
calculateService.stateProperty().addListener((ObservableValue<? extends Worker.State>
observableValue, Worker.State oldValue, Worker.State newValue) -> {
75.
switch (newValue) {
76.
case FAILED:
77.
case CANCELLED:
78.
case SUCCEEDED:
79.
scene.setCursor(oldCursor);
80.
calculateItem.setDisable(false);
81.
calculateButton.setDisable(false);
82.
break;
83.
}
84.
});
85.
calculateService.start();
86.
}
87.
88.
public static void main(String[] args) {
89.
launch(args);
90.
}
91. }
Nous pouvons galement voir que nous n'avons pas eu crer un nouveau thread manuellement ni d'avoir
nous synchroniser dessus. Cependant le calcul s'est bien droul dans un autre fil d'excution diffrent du JavaFX
Application Thread.
-9-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Service<V> : une classe qui est instancie et manipule par l'UI pour crer, grer et superviser la tche de
longue dure ;
ScheduledService<V> : une classe qui est instancie et manipule par l'UI pour crer, grer et superviser la
tche de longue dure qui peut se rpter intervalles rguliers. JDK8 ou ultrieur ;
Task<V> : une classe qui est instancie et manipule par le service ou le service rptable pour excuter la
tche de longue dure dans un thread spar.
III-B - javafx.concurrent.Service<V>
La classe Service est destine tre utilise et manipule dans l'UI. Son seul vrai but est de crer une tche (Task)
qui sera excute en arrire-plan dans un autre thread. Une instance de Service est destine tre rutilisable,
vous pouvez donc conserver une rfrence sur une instance de Service et l'excuter plusieurs fois d'affile.
Pour instancier un service, il suffit de crer une nouvelle classe anonyme qui tend Service<V> et de surcharger la
mthode abstraite createTask() pour qu'elle cre une Task<V> du mme type que le service :
1. Service<Image> imageLoadingService = new Service<Image>(){
2.
3.
@Override
4.
protected Task<Image> createTask() {
5.
// Instancier et retourner une Task<Image> ici.
- 10 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
6.
}
7. };
III-C - javafx.concurrent.Task<V>
C'est cette classe qui sera amene faire le calcul, la requte ou le traitement de longue dure et c'est dans la
mthode call() de cette classe que la tche est effectue ; cette mthode sera appele dans un thread spar,
diffrent du JavaFX Application Thread.
Contrairement Service, une Task est destine n'tre excute qu'une seule et unique fois. Une tche n'est pas
rutilisable !
Pour crer une tche, il suffit de crer une nouvelle classe anonyme qui tend Task<V> et de surcharger la mthode
call() pour qu'elle renvoie une instance du type appropri :
1. Task<Image> imageLoadingTask = new Task<Image>(){
2.
3.
@Override
4.
protected Image call() throws Exception {
5.
// Charger l'image ici.
6.
Image image = ...
7.
return image;
8.
}
9. };
En plus des calculs, accs IO, requte web ou BD ou autre, vous pouvez faire tout ce que vous faites habituellement
dans un thread au cours de ce traitement : boucle infinie, appel Thread.sleep(), etc. sans pour autant que cela
ne bloque l'UI.
Attention cependant, toute exception qui n'est pas catche dans ce traitement remontera au niveau suprieur et
passera automatiquement la tche en l'tat FAILED en plus d'arrter le calcul ou le traitement en cours.
III-D - Javafx.concurrent.ScheduledService<V>
La classe ScheduledService, introduite dans le JDK8 permet de crer des services qui se rptent intervalles
rguliers. Elle fonctionne comme la class Service mais dispose de proprits supplmentaires pour grer la rptition
ainsi que les conditions de gestion des checs.
- 11 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Un ScheduledService, se relance automatiquement lorsque son excution prcdente s'est termine correctement
une fois le temps d'attente spcifi par le programmeur coul. Il peut galement se relancer en cas d'erreur
d'excution suivant les conditions de gestion des checs qui ont t spcifies.
IV - Utiliser un service
Vous serez donc amen utiliser la classe Service depuis le code de votre UI, en raction un clic sur un bouton, dans
un menu, une slection dans une table, une liste ou un menu droulant, etc. La majorit de ces actions s'excutera
donc dans le JavaFX Application Thread. Voyons donc maintenant comment utiliser un service.
L'appel la mthode start() du service, provoquera le dmarrage de la tche de fond dans un nouveau thread.
IV-B - Annulation
Pour annuler un service en cours d'excution, il suffit d'appeler la mthode cancel() du service depuis l'UI (par
exemple, un bouton). Lorsque la mthode cancel() est appele, l'tat du service et de la tche passe CANCELLED.
Attention, cela n'aura pas pour effet d'arrter la tche immdiatement ! Comme nous le verrons ultrieurement,
vous devrez prendre des prcautions supplmentaires dans la tche pour vous assurer qu'elle termine bien son
excution.
- 12 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
1. imageLoadingService.cancel();
Il est galement possible d'appeler la mthode restart() qui fera exactement la mme chose que le couple reset()
+ start() :
1. imageLoadingService.restart();
Il est aussi possible de mettre des ChangeListener sur chacune de ces proprits pour transmettre leurs changements
de valeur sur d'autres lments de l'UI.
- 13 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
24.
[...]
25.
break;
26.
case SUCCEEDED:
27.
// La tche s'est correctement termine.
28.
[...]
29.
break;
30.
}
31. });
32. imageLoadingService.start();
Code JDK8
- 15 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
Code JDK8
1.
2.
3.
4.
5.
6.
7.
8.
9.
- 16 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
10. imageLoadingService.start();
Si trop d'appels ces mthodes ont lieu dans un court laps de temps, il y aura agrgation des diffrents appels et
seules les dernires valeurs seront transmises l'UI. Ainsi certains messages peuvent tre perdus et la progression
peut sauter des valeurs si elle est trop rapide.
Dans le cas de boucles ou de progressions obtenues par calcul, il faut galement faire attention au fait que
updateProgress() gnrera une exception de type IllegalArgumentException si la valeur d'avancement devient
strictement suprieure la valeur maximum attendue.
V-B - Annulation
Comme nous l'avons vu prcdemment, appeler la mthode cancel() du service met la tche dans l'tat CANCELLED,
mais cela ne suffit pas en soi pour arrter l'excution de la tche. Dans votre traitement, vous devez vrifier
intervalles rguliers la valeur retourne par la mthode isCancelled() de la tche et interrompre le calcul en cours
le cas chant . Par exemple, la tche suivante effectue 1 000 000 itrations et vrifie si la tche a t annule
chaque itration, interrompant la boucle si c'est le cas.
1. return new Task<Integer>() {
2.
@Override
3.
protected Integer call() throws Exception {
4.
final int maxIterations = 1000000;
5.
int iterations = 0;
6.
for (iterations = 0; iterations < maxIterations; iterations++) {
7.
// Arrt de la boucle si la tche est annule.
8.
if (isCancelled()) {
9.
break;
10.
}
11.
// On envoie un nouveau message.
- 17 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
12.
updateMessage("iteration "+ (iterations+1));
13.
// On change l'avancement de la tche.
14.
updateProgress(iterations, maxIterations);
15.
[...]
16.
}
17.
return iterations;
18.
}
19. };
Il n'existe pas de mthode pour l'tat READY, car il s'agit de l'tat par dfaut d'une tche sa cration.
- 18 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Il faudra cependant, dans la mthode call(), prendre des prcautions pour que les valeurs soient settes dans le
JavaFX Application Thread et non pas dans le thread de la tche. En effet, gnralement des rsultats partiels ne
sont intressants que dans le cadre d'un affichage dans une UI. Or, une fois affiches dans une scne, les proprits
des contrles JavaFX doivent tre uniquement accdes via le JavaFX Application Thread.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
@Override
protected Integer call() throws Exception {
final int maxIterations = 1000000;
int iterations = 0;
for (iterations = 0; iterations < maxIterations; iterations++) {
// Arrt de la boucle si la tche est annule.
if (isCancelled()) {
break;
}
// ! La proprit doit tre manipule dans la JavaFX Application Thread !
final int it = iterations;
Platform.runLater(new Runnable() {
@Override
public void run() {
partialResult.set(it);
}
});
}
- 19 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
19.
20.
return iterations;
Il faut faire galement attention au fait qu'ici, il n'y a pas de fusion ou agrgation des envois de valeurs partielles
sur le JavaFX Application Tread. Cela peut donc provoquer une monopolisation ou une surcharge du thread par la
tche cause du trop grand nombre de requtes Platform.runLater() et nous ramener notre problme de blocage
initial. Ici, cet exemple ne fait pas moins de 1 000 000 de requtes Platform.runLater() dans une boucle rapide
sans aucune pause ! Cela peut faire que l'application cesse de rpondre, ne puisse plus se redimensionner ou plante
carrment, bref on perdrait tous les avantages lis l'utilisation d'un service !
Il faudra donc penser amnager des temps de repos en appelant Thread.sleep() intervalles rguliers de manire
ce que le JavaFX Application Thread puisse continuer s'excuter et vacuer les vnements en attente.
1.
@Override
2.
protected Integer call() throws Exception {
3.
final int maxIterations = 1000000;
4.
int iterations = 0;
5.
for (iterations = 0; iterations < maxIterations; iterations++) {
6.
// Arrt de la boucle si la tche est annule.
7.
if (isCancelled()) {
8.
break;
9.
}
10.
// ! La proprit doit tre manipule dans la JavaFX Application Thread !
11.
final int it = iterations;
12.
Platform.runLater(new Runnable() {
13.
@Override
14.
public void run() {
15.
partialResult.set(it);
16.
}
17.
});
18.
// Interragir ainsi avec le JavaFX Application Thread demande de lui laisser un peu le temps de respirer.
19.
try {
20.
Thread.sleep(50);
21.
} catch (InterruptedException ie) {
22.
if (isCancelled()) {
23.
break;
24.
}
25.
}
26.
}
27.
return iterations;
28.
}
On pourrait galement modifier le code pour faire en sorte que les mises jour de l'UI arrivent tous les 1000 lments
par exemple, de manire rduire le nombre de mises jour effectues.
V-D-2 - JDK 8
Le JDK 8 a ajout la possibilit d'invoquer la mthode updateValue() dans le corps de la tche pour mettre jour
le contenu de la proprit value de l'objet Task (et de son service parent). Il suffira alors de placer un couteur de
type InvalidationListener ou ChangeListener sur cette proprit pour tre mis au courant de ses changements de
valeur au cours du calcul.
La mthode updateValue() peut tre invoque depuis n'importe quel thread mme celui dans lequel s'excute la
tche. Tout comme les autres mthodes updateXXX(), les appels sont fusionns lorsqu'ils sont trop nombreux, ce
qui fait que certains changements de valeur peuvent tre omis.
Code JDK8
@Override
protected Integer call() throws Exception {
final int maxIterations = 1000000;
- 20 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Code JDK8
int iterations = 0;
for (iterations = 0; iterations < maxIterations; iterations++) {
// Arrt de la boucle si la tche est annule.
if (isCancelled()) {
break;
}
// ! La proprit doit tre manipule dans la JavaFX Application Thread !
final int it = iterations;
updateValue(it);
}
}
return iterations;
- 21 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
Si la tche prend plus de temps s'excuter que la dure spcifie dans la priode, ou si la priode est vide (ex. :
Duration.ZERO ou une dure indtermine), le service se relance alors immdiatement aprs la fin de la tche sans
plus attendre. De plus, le service ne peut interrompre une tche en cours si elle dpasse le temps d'attente indiqu
pour la priode.
1. service.setBackoffStrategy(service ->
Duration.seconds(service.getCurrentFailureCount() * 5)); // On ajoute 5 secondes d'attente entre chaque chec.
2. service.setMaximumCumulativePeriod(Duration.minutes(10)); // Au maximum on attendra 10 minutes avant la prochai
VII - Conclusion
Vous savez dsormais comment lancer une tche de fond en JavaFX, ceci vous permettra de lancer tous vos
traitements longs en arrire-plan de l'UI sans pour autant geler votre interface graphique.
VIII - Remerciements
Je tiens remercier toute l'quipe du forum
Dveloppez ainsi que
Mickael Baron et
Gueritarish pour
leurs suggestions et leurs relectures du prsent article. Je tiens galement remercier Claude Leloup pour ses
corrections orthographiques.
- 22 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/
Tutoriel sur l'excution d'une tche de fond en JavaFX par Fabrice Bouy
IX - Liens
- 23 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de
prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Fabrice Bouy. Aucune reproduction,
mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.
http://fabrice-bouye.developpez.com/tutoriels/javafx/gui-service-tache-de-fond-thread-javafx/