Ecco cosa ho fatto per l'app della mia azienda, questo è un pseudo codice per motivi legali, ma la cosa fondamentale è che se lo schermo non risponde, riavvierà la GUI. Ogni volta che usi SwingUtilities per avviare l'EDT, nello stesso blocco di init, crea due thread watcher. Un thread eseguirà semplicemente un'azione sul thread EDT utilizzando le utilità Swing. Un altro thread monitorerà il primo thread per vedere se sente che il primo thread è reattivo. Il primo thread riconoscerà la reattività solo se può eseguire un comando molto semplice.
set isEDTCheck true durante l'esecuzione in modo normale, falso in modalità debug (altrimenti si ottiene costantemente riavviato.
if (isEDTCheck) {
new Thread("EDTHeartbeat") {
@Override
public void run() {
Runnable thisThingYouDo = new Runnable() {
public void run() {
int x = 0;
}
};
while (true) {
// first thread says we are waiting, aka bad state
edtwait=true;
try {
javax.swing.SwingUtilities.invokeAndWait(thisThingYouDo);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// first thread says we are not waiting, good state
edtwait=false;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread("EDTValidator") {
@Override
public void run() {
while (true) {
// is first thread in bad state?
if (edtwait) {
try {
Thread.sleep(3000);
// after 3 seconds are we still in bad state? if so, get rid of initial frame, pop up a dialog box in AWT that does no commands
if (edtwait) {
mainFrame.setVisible(false);
new Dialog();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
public class Dialog extends Frame {
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
Frame f = null;
public Dialog() {
f = this;
hasSomethingBeenEntered=false;
this.setTitle("APP PROBLEM DETECTED");
this.setSize(WIDTH, HEIGHT);
this.setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() - myapp.width, 0);
Panel p1 = new Panel() {
@Override
public void paint(final Graphics g) {
int left = Dialog.WIDTH/2 - 45; // don't use WIDTH shadowed by Panel class
int top = Dialog.HEIGHT/2 - 20; // same as above
g.drawString("APP HAS DETECTED A PROBLEM", left, top);
}
};
this.add("Center", p1);
this.setAlwaysOnTop(true);
TextArea tb = new TextArea("APP HAS DETECTED A MAJOR PROBLEM\nIT WILL NOW RESTART IN 5 SECONDS");
this.add(tb);
this.setVisible(true);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
restartApp();
}
private void restartApp() {
Runtime.getRuntime().exec("cmd /c start cmd.exe /K \"cd C:\\Progra~1\\Common~1 && C:\\Progra~1\\Common~1\\MyAppDir\\myjavaapp.jar\"");
System.exit(0);
}
fonte
2012-08-02 19:49:21
Anch'io voglio fare la trama run() del codice in una classe che estende SwingWorker, ed esegui quel codice computazionalmente pesante nella funzione doInBackground() e poi usa la funzione done() per aggiornare il mio display? La mia GUI sarà ancora attiva mentre il calcolo sta avendo luogo? – smuggledPancakes
@ user464095: Sì, esattamente. – ColinD
Bingo. Questo è ciò che SwingWorker fa ed è per. –