IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

EDT/SwingWorker Java Discussion :

Arreter un SwingWorker


Sujet :

EDT/SwingWorker Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut Arreter un SwingWorker
    J'ai une question sur les SwingWorker, j'utilise un JTree qui présente une arborescence de dossiers et lorsque l'utilisateur sélectionne un dossier je lance un SwingWorker qui affiche dans un JPanel positionné à coté les images du répertoire.
    Mon SwingWorker fait un publish toutes les 10 images pour afficher le contenu du répertoire avant de l'avoir analysé en entier.

    Mon problème se pose lorsque l'utilisateur sélectionne un autre dossier dans l'arborescence avant que le précédent SwingWorker soit terminé.
    Les deux mettent ajoutent les images dans le JPanel et ça devient le bazard.

    J'ai essayé d'arreter mon SwingWorker en faisant un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	if (lp != null) {
    		while (lp.isDone() == false) {
    			lp.cancel(true);
    		}
    	}
    Sachant que lp est mon SwingWorker et est déclaré dans la classe comme ceci : private ListLocalThumbnailsSW lp;
    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
     
        @Override
        protected Object doInBackground() throws Exception {
            logger.log(Level.INFO, "+ ListLocalThumbnailsSW");
            tl.clearAll();
            FolderNode folderNode = (FolderNode) e.getPath().getLastPathComponent();
            logger.log(Level.INFO, "Recherche des images dans le repertoire : {0}", folderNode.getPathFolder());
            File currentFolder = new File(folderNode.getPathFolder());
            File[] listImage = currentFolder.listFiles(new ImageFilter());
            logger.log(Level.INFO, "Le repertoire : {0} contient {1} image(s)", new Object[]{folderNode.getPathFolder(), listImage.length});
            List<LocalPhoto> tmpLst = new ArrayList<LocalPhoto>();
            for (int i = 0; i < listImage.length; i++) {
                if(Thread.interrupted()) {
                    logger.log(Level.INFO, "Arret du thread");
                    return null;
                }
                LocalPhoto localPhoto = new LocalPhoto(listImage[i]);
                tmpLst.add(localPhoto);
                if (tmpLst.size() == PACKET_SIZE) {
                    logger.log(Level.FINE, "Publication de {0} images", new ArrayList<LocalPhoto>(tmpLst).size());
                    publish(new ArrayList<LocalPhoto>(tmpLst));
                    tmpLst.clear();
                }
            }
            logger.log(Level.FINE, "Publication de {0} images", new ArrayList<LocalPhoto>(tmpLst).size());
            if(Thread.interrupted()) return null;
            publish(new ArrayList<LocalPhoto>(tmpLst));
     
            return null;
        }
    Je vois d'ou le problème peut venir, dans ma méthode publish j'appelle une méthode ( replaceAll(List<LocalPhoto> localPhotoList) )de mon Jpanel qui ajoute les images
    Si je demande l'interruption de mon SwingWorker il s'arrete mais cette méthode tourne encore pendant que cette méthode tourne mon nouveau SwingWorker démarre et à la deuxième ligne dans le doInBackground() je fais un tl.clearAll() qui efface le contenu de mon JPanel, si jamais ma méthode replaceAll(List<LocalPhoto> localPhotoList) n'a pas fini de s'executer elle continu d'ajouter des images.

    J'imagine qu'il y a un problème de synchronisation dans mes thread mais je ne vois pas comment le régler.

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    On pourrait voir le code manquant ( process() et replaceAll() ).

    Comme tu le dit le problème ne vient pas du SW puisque tu dit qu'il s'arrête bien, mais des processus que tu fais dans l'EDT... donc il nous faut voir ce code.


    a++

    PS : Une remarque : tu t'embêtes à passer les valeurs dans publish() par bloc alors que tu peux les passer une à une (elle seront regroupé si besoin)

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    Merci pour la rapidité de la réponse voici les informations demandées :

    Je passe mes informations par bloc car j'ai remarqué que le problème se posait moins quand je fais comme ça mais je vais modifier pour les passer une par une.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        @Override
        protected void process(List<List<LocalPhoto>> chunks) {
            for (List<LocalPhoto> lp : chunks) {
                tl.replaceAll(lp);
            }
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        public void replaceAll(List<LocalPhoto> localPhotoList) {
            for (Iterator<LocalPhoto> it = localPhotoList.iterator(); it.hasNext();) {
                LocalPhoto localPhoto = it.next();
                add(new ThumbnailPanelUI(localPhoto));
                nbImage++;
            }
            revalidate();
        }

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Je viens de relire ton message et je pense avoir mis le doigt sur le problème :
    Citation Envoyé par pedrollane Voir le message
    mon nouveau SwingWorker démarre et à la deuxième ligne dans le doInBackground() je fais un tl.clearAll() qui efface le contenu de mon JPanel
    Tu ne respectes pas la règle de l'EDT qui dit que toutes les modifications de l'UI DOIVENT être faite dans l'EDT.


    Explications :
    • Lorsque tu passes les valeurs via publish(), elles sont mises en attentes pour être envoyer à l'EDT (via la méthode invokeLater()).
      Comme son nom l'indique ce n'est pas forcément exécuter immédiatement. En fait c'est mis dans une file d'attente qui traitera les demandes de manière séquentielle...
    • En modifiant ton JPanel depuis un autre thread de l'EDT, tu ne peux garantir le bon ordonnancement des tâches. Ainsi tu effaces la liste, mais bien que ton SW précédent soit bien arrêté il peux rester des tâches en attente dans la pile de l'EDT... ce qui aboutit à l'ajout des images...



    Cet appel à clearAll() doit être fait dans l'EDT via un invokeLater() afin de s'assurer qu'il sera exécuté au bon moment


    a++

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
                SwingUtilities.invokeLater(new Runnable() {
     
                    @Override
                    public void run() {
                        JPloaderNGUI.getInstance().getPanelPreview().clearAll();
                    }
                });
    Je viens d'ajouter ça dans mon code juste avant le execute() de mon SwingWorker mais ça ne change rien.

    Pour moi le invokeLater garanti l'execution dans l'EDT mais pas l'execution après mon publish sur le répertoire précedemment sélectionné, et c'est ça qui pose problème.

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par pedrollane Voir le message
    Je viens d'ajouter ça dans mon code juste avant le execute() de mon SwingWorker mais ça ne change rien.
    Et après le cancel() du SW précédent ?


    Citation Envoyé par pedrollane Voir le message
    Pour moi le invokeLater garanti l'execution dans l'EDT mais pas l'execution après mon publish sur le répertoire précedemment sélectionné, et c'est ça qui pose problème.
    Si ton SW est déjà arrêté, cela signifie qu'il doit déjà avoir soumis ses tâches à l'EDT via invokeLater(). Donc théoriquement si tu fais un invokeLater() il s'exécutera après...


    a++

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    Merci de d'interresser à mon problème et de proposer des solutions.

    Voici le code que j'ai pour démarrer mon traitement lors d'un clic sur un dossier du JTree :

    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
     
                if (lp != null) {
                    while (lp.isDone() == false) {
                        lp.cancel(true);
                    }
                }
                SwingUtilities.invokeLater(new Runnable() {
     
                    @Override
                    public void run() {
                        JPloaderNGUI.getInstance().getPanelPreview().clearAll();
                    }
                });
                lp = new ListLocalThumbnailsSW(e, JPloaderNGUI.getInstance().getPanelPreview());
                lp.execute();
    Les deux méthodes qui sont dans mon JPanel personnalisé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        public void clearAll() {
                removeAll();
                revalidate();
     
        }
     
        public void replaceAll(LocalPhoto localPhoto) {
                add(new ThumbnailPanelUI(localPhoto));
                revalidate();
     
        }
    Peut être que mon problème vient de l'utilisation du SwingWorker ce n'est peut être pas adapté à mon cas. Je vais essayer de me documenter plus.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    Après quelques recherches, je viens de voir qu'une autre personne à le même problème que moi ici http://stackoverflow.com/questions/1...adpoolexecutorje vais tester les solutions qui sont données.

    Mon problème se pose si je sélectionne plusieurs dossiers à la suite très rapidement.
    D'après le lien ci-dessus ils sont mis dans la file d'attente ThreadPoolExecutor mais ne peuvent pas être arreté par cancel() car ils ne sont pas démarrés.
    Quand ils démarrent ils mettent à jour mon JPanel de façon concurrente.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    J'ai fini par résoudre le problème j'ai ajouté un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(!Thread.interrupted())
    dans le publish et maintenant je fais appel au clearAll() lors du premier appel au Publish().

    J'ai essayé sans succès les solutions proposées dans la discution dont j'avais donné le lien plus haut.

  10. #10
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Par défaut
    Salut,

    Tu as pensé a invalider ton action qui lance le traitement tant que celui en cours n'est pas fini ?

    Ou c'est vraiment un comportement que tu veux garder ?

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 11
    Par défaut
    Je souhaite garder ce comportement car lister le contenu d'un dossier qui contient beaucoup de photo prends du temps à cause de la génération des miniatures.

    Donc je ne souhaite pas empêcher l'utilisateur de sélectionner un autre dossier tant que l'action n'est pas finie.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SwingWorker] Arret d'une méthode sans raisons..
    Par Invité dans le forum Général Java
    Réponses: 2
    Dernier message: 14/02/2008, 17h34
  2. j'arrive pas a arreter mon thread d'arriere-plan
    Par ms91fr dans le forum Langage
    Réponses: 6
    Dernier message: 06/06/2003, 21h36
  3. [UDP][Socket] perte de paquets et arret d'ecoute sur port
    Par Guismo1979 dans le forum Développement
    Réponses: 6
    Dernier message: 02/01/2003, 12h13
  4. probleme a l'arret de threads
    Par Sei dans le forum C++Builder
    Réponses: 5
    Dernier message: 16/12/2002, 12h15
  5. Detection arret de windows
    Par philippe30 dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 21/09/2002, 18h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo