Problemi con i Thread

di il
11 risposte

Problemi con i Thread

Buonasera a tutti,
pensavo di aver risolto e invece sono qui a chiedervi aiuto...

Descrizione:

Ho due Thread, il primo gestisce una label con un testo lampeggiante "Backup in corso" mentre l'altro Thread gestisce il backup di un file.

Thread n° 1
public class ThreadProgresso implements Runnable {

private JLabel labelBackup;

ThreadProgresso(JLabel labelBackup) {
this.labelBackup = labelBackup;
}

public void run() {
while (true) {
labelBackup.setVisible(true);
labelBackup.setBackground(Color.RED);;
labelBackup.setBorder(BorderFactory.createLineBorder(Color.BLACK));
labelBackup.repaint();
for (int i = 0; i < 3; ++i) {
labelBackup.setText("BACKUP IN CORSO");
try {
Thread.sleep(500);
} catch (InterruptedException e) {

e.printStackTrace();
}
labelBackup.repaint();
labelBackup.setText("");
try {
Thread.sleep(500);
} catch (InterruptedException e) {

e.printStackTrace();
}
labelBackup.repaint();
}
}
}
}

Thread n °2
public class ThreadBackup implements Runnable{

String pathPercorso = new String();

public ThreadBackup(String pathPercorso){
this.pathPercorso = pathPercorso;
}

public void run() {

BackupManager backupManager = new FBBackupManager();
backupManager.setHost("localhost");
backupManager.setPort(3050);
backupManager.setUser("SYSDBA");
backupManager.setPassword("masterkey");
backupManager.setLogger(System.out);
backupManager.setVerbose(true);
backupManager.setDatabase(pathPercorso);
backupManager.setBackupPath("c:/archivioDiBackup.bak");
try{
backupManager.backupDatabase();
Thread.sleep(10);
}
catch(Exception e){
e.printStackTrace();
}
}
IL MAIN è cosi composto:
...
..
try {
//avvio maschera BackupInCorso creando un nuovo thread "wait"
ThreadProgresso tp = new ThreadProgresso(labelBackup);
Thread wait = new Thread(tp);
wait.start();
wait.setPriority(Thread.MAX_PRIORITY);

//avvio backup creando nuovo thread "backup"
String percorsoBackup = txtDestination.getText();
ThreadBackup tb = new ThreadBackup(percorsoBackup);
Thread backup = new Thread(tb);
backup.start();
backup.join();

//Quando finisci backup mostrami messaggio di avviso

JOptionPane.showMessageDialog(frmArcdestination, "Backup concluso con successo"");

}

catch (Exception e1) {

e1.printStackTrace();
}
}

PROBLEMA RISCONTRATO:

il primo Thread nonostante sia in cima al codice, nonostante gli venga assegnata la massima priorita risulta essere "invisibile", il programma lo ignora e va subito sul secondo Thread. dopo che il secondo thread ha terminato di backappare il file, appare contemporaneamente al messaggio di fine Backup anche la label con la scritta backup lampeggiante (Primo thread).

Mi potete dare qualche dritta per risolvere?

Grazie e buona serata

11 Risposte

  • Re: Problemi con i Thread

    Fasyrio ha scritto:


    il primo gestisce una label con un testo lampeggiante "Backup in corso"
    Il punto è che l'accesso alla interfaccia utente (salvo POCHI casi documentati) va fatto SOLO nel contesto del Event Dispatch Thread.
    Mentre qui si vede che nel run() vai a fare setVisible, setBackground ecc... Questo è INAPPROPRIATO.

    Se vuoi far "lampeggiare" una label (quindi una cosa abbastanza "tranquilla" come tempistiche) sarebbe meglio usare un javax.swing.Timer, i cui eventi sono dispacciati ad un ActionListener nel EDT (quindi non ci sono problemi).

    Fasyrio ha scritto:


    mentre l'altro Thread gestisce il backup di un file.

    //avvio maschera BackupInCorso creando un nuovo thread "wait"
    ThreadProgresso tp = new ThreadProgresso(labelBackup);
    Thread wait = new Thread(tp);
    wait.start();
    wait.setPriority(Thread.MAX_PRIORITY);

    //avvio backup creando nuovo thread "backup"
    String percorsoBackup = txtDestination.getText();
    ThreadBackup tb = new ThreadBackup(percorsoBackup);
    Thread backup = new Thread(tb);
    backup.start();
    backup.join();

    //Quando finisci backup mostrami messaggio di avviso

    JOptionPane.showMessageDialog(frmArcdestination, "Backup concluso con successo"");
    Giusto per capire io ... quest'ultimo pezzo di codice lo fai a seguito di un qualche evento, es. in un actionPerformed() ?
    Perché se sì, sei nel EDT, che NON va mai tenuto bloccato. E invece ..... quel backup.join(); TIENE bloccato il EDT.
    Quindi il ThreadBackup "gira" e fa quello che deve fare. Il ThreadProgresso pure STA girando ma il EDT è bloccato nel join(), quindi comunque non vedi alcun aggiornamento.
  • Re: Problemi con i Thread

    Ciao anbin, ..come sempre grazie per l'interessamento! Cerco di risponderti:

    1) il setVisible..setBackground...ecc mi sono dimenticato di toglierli prima di postare il codice, erano solo dei tentativi inutili che stavo facendo.

    2 ) Si, l'ultimo pezzo di codice lo faccio a seguito della pressione di un pulsante. Per quanto riguarda il backup.join() hai perfettamente ragione mi tiene bloccato il EDT; se non inserisco backup.join i due thread si avviano entrambi, ma si verificano altri due problemi diversi:
    - a) Mi appare immediatamente il messaggio che sta alla fine del codice, con all'interno dello showMessageDialog "Backup terminato"! Una volta chiusa questa finestra di informazione il backup avviene regolarmente e la finestra con scritto backup in corso lampeggia.
    -b) dopo che il backup ha realmente terminato, non mi accorgo di nulla pero (se non dalla console) in quanto il thread 1 continua a lampeggiare all'infinito.
  • Re: Problemi con i Thread

    Fasyrio ha scritto:


    1) il setVisible..setBackground...ecc mi sono dimenticato di toglierli prima di postare il codice, erano solo dei tentativi inutili che stavo facendo.
    Ma anche i setText sono inappropriati lì direttamente in quel run()

    Fasyrio ha scritto:


    - a) Mi appare immediatamente il messaggio che sta alla fine del codice, con all'interno dello showMessageDialog "Backup terminato"! Una volta chiusa questa finestra di informazione il backup avviene regolarmente e la finestra con scritto backup in corso lampeggia.
    Il fatto di attendere la terminazione del thread devi farlo tu e ovviamente in altro modo.

    Fasyrio ha scritto:


    -b) dopo che il backup ha realmente terminato, non mi accorgo di nulla pero (se non dalla console) in quanto il thread 1 continua a lampeggiare all'infinito.
    Idem, devi preoccupartene tu. Riuscendo ad attendere la terminazione del thread SENZA tenere impegnato il EDT, riusciresti a: 1) mostrare la dialog di backup terminato e 2) terminare il lampeggio (se avessi usato un javax.swing.Timer basta un banalissimo stop() sul timer).
  • Re: Problemi con i Thread

    Provo a smanettarci un attimino provo cosi come hai detto tu: javax.swing.Timer

    gentilissimo!! Ti ringrazio
  • Re: Problemi con i Thread

    Non so in quanti punti della applicazione hai bisogno di usare una label "lampeggiante". Se solo uno, puoi anche fare la gestione un po' al volo e non riutilizzabile.
    Se ne hai già 2, 3, ecc... puoi sfruttare la oop. Estendi JLabel:

    public class BlinkingLabel extends JLabel {
    // ....
    }

    Dentro ci tieni il Timer e altro necessario, come due metodi es. startBlink() e stopBlink()

    L'uso quindi sarebbe molto semplice, pulito e oltretutto riutilizzabile.
  • Re: Problemi con i Thread

    No anbin..mi dispiace ma non ne vengo a capo.. ho trasformato le due classi che descrivono il thread da implements runnable a extends TimerTask. Ho successivamente creato due task, uno con la label "backup lampeggiante" e l'altro che esegue il backup. Ottengo gli stessi identici problemi riscontrati quanto sopra. Ho bisogno di usare il label lampeggiante solo in un punto dell'applicazione..una gestione al volo sarebbe perfetta..pero non ci riesco
  • Re: Problemi con i Thread

    Fasyrio ha scritto:


    ho trasformato le due classi che descrivono il thread da implements runnable a extends TimerTask.
    Cosa centra TimerTask??
    Io per il lampeggio parlavo prima di javax.swing.Timer .... non di java.util.Timer
  • Re: Problemi con i Thread

    No no non c'entra niente hai ragione...cmq ho provato anche con javax.swing.Timer ma niente..mi secca questa cosa. Purtroppo son bloccato,, mi hai dato info preziose..mi son documentato..ma purtroppo non ne vengo a capo, non so che dire
  • Re: Problemi con i Thread

    Fasyrio ha scritto:


    ho provato anche con javax.swing.Timer ma niente..
    javax.swing.Timer è specifico di Swing, dispaccia gli eventi di timing tramite un ActionListener, quindi sei nel Event Dispatch Thread quando ricevi l'evento. Pertanto puoi tranquillamente aggiornare label o quant'altro in questo contesto. Chiaramente siccome ricevi solo eventi ad intervalli di tempo, per poter far "lampeggiare" una label devi "switchare" tu tra stato on e stato off, ad esempio tenendo una variabile booleana.

    Fasyrio ha scritto:


    mi secca questa cosa. Purtroppo son bloccato,, mi hai dato info preziose..mi son documentato..ma purtroppo non ne vengo a capo, non so che dire
    Capisco ... ma servirebbe solo un po' più di studio/impegno.
  • Re: Problemi con i Thread

    Scritto "al volo" e minimale:
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class LabelBlinkFrame extends JFrame {
        private static final long serialVersionUID = 1L;
    
        private JLabel label;
        private boolean state;
    
        public LabelBlinkFrame() {
            super("Prova Blink Label");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(400, 300);
            setLocationRelativeTo(null);
    
            label = new JLabel("<html><span style='font-size:40px'>PROVA</span></html>");
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setOpaque(true);
            add(label);
    
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (state = !state) {
                        label.setForeground(Color.WHITE);
                        label.setBackground(Color.RED);
                    } else {
                        label.setForeground(Color.RED);
                        label.setBackground(Color.WHITE);
                    }
                }
            });
            timer.start();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new LabelBlinkFrame().setVisible(true);
                }
            });
        }
    }
  • Re: Problemi con i Thread

    Grazie mille andbin!!! l'esempio mi risolve appieno la problematica! Scusami se ti ho stressato abbastanza su questa cosa ..
Devi accedere o registrarti per scrivere nel forum
11 risposte