Bonjour,
Il s'agit d'un problème faisant suite à 1 discussion précédente, que je délocalise, pour ne pas polluer le sujet initial de l'auteur (voir Actions concurrentes dans l'EDT)
Le sujet est assez simple, et la solution doit l'être tout autant...
mais pour l'instant, je ne l'ai pas trouvée.
Il s'agit d'exécuter une action longue dans Swing, sans bloquer l'EDT, et en donnant la possibilité à l'utilisateur :
- de démarrer la tâche longue
- de la mettre en pause ou de la reprendre
- de la stopper définitivement
J'ai une classe permettant de gérer ce type de tâche, mal, puisque la méthode sensée mettre la tâche en pause bloque l'EDT (méthode sleep en rouge)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47public abstract class MyTask implements Runnable { private int delai = 1000; private volatile Thread currentThread = null; public void run() { currentThread = Thread.currentThread(); while (!currentThread.isInterrupted() && continueCondition()) { doMyTask(); try { Thread.sleep(delai); } catch (InterruptedException exception) { onCancelled(); break; } } } public void cancel() { currentThread.interrupt(); } //Pose problème : méthode bloquant l'EDT public void sleep() { synchronized (this) { try { while (!currentThread.isInterrupted()) { this.wait(); } } catch (InterruptedException e) { onCancelled(); } } } public void wakeUp() { synchronized (this) { this.notify(); } } public abstract void doMyTask(); public abstract boolean continueCondition(); public abstract void onCancelled(); }
- doMyTask permet d'implémenter 1 tâche atomique (1 parcours de boucle...)
- continueCondition est ta condition de continuité (de la boucle par exemple)
- onCancelled, la méthode à implémenter en cas d'annulation
Ci dessous une classe de test implémentant MyTask (avec une tâche bidon consistant à boucler...):
Logiquement, le thread de la tâche n'est pas lancé dans l'EDT :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 public class TestThreads extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; private JPanel mainPanel; private JButton btStart; private JButton btStop; private JButton btSleep; private JButton btWakeUp; private MyTask mytask; private Thread currentThread; private JLabel lblCompteur; private int compteur = 0; public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { private TestThreads t; @Override public void run() { t = new TestThreads(); } }); } public TestThreads() { super(); // Tâche mytask = new MyTask() { @Override public void onCancelled() { compteur = 0; updateLblCompteur(); } @Override public void doMyTask() { compteur++; updateLblCompteur(); }; @Override public boolean continueCondition() { return compteur < 10000; } }; // Fenêtre JFrame fen = new JFrame("Test threads"); fen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fen.setLayout(new BorderLayout()); mainPanel = new JPanel(new FlowLayout()); lblCompteur = new JLabel("0"); mainPanel.add(lblCompteur); btStart = getButton("Start"); btStop = getButton("Stop"); btSleep = getButton("Sleep"); btWakeUp = getButton("Reveil"); fen.add(mainPanel, BorderLayout.NORTH); fen.pack(); fen.setVisible(true); } /** * Création d'un bouton * * @param text * @return */ private JButton getButton(String text) { JButton bt = new JButton(text); bt.addActionListener(this); mainPanel.add(bt); return bt; } private void updateLblCompteur() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { lblCompteur.setText(compteur + ""); } }); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(btStart)) { currentThread = new Thread(mytask); currentThread.start(); } if (e.getSource().equals(btStop)) mytask.cancel(); if (e.getSource().equals(btSleep)) { // Problème !!!!!!!!! Méthode bloquante mytask.sleep(); System.out.println("pas sleep"); } if (e.getSource().equals(btWakeUp)) mytask.wakeUp(); } }
donc pourquoi le wait sur mytask bloque t-il l'EDT ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 currentThread = new Thread(mytask); currentThread.start();







Répondre avec citation
Partager