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

Windows Presentation Foundation Discussion :

Fonction de recherche de fichier en multi thread


Sujet :

Windows Presentation Foundation

  1. #1
    Membre confirmé Avatar de Takumi
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2009
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 163
    Par défaut Fonction de recherche de fichier en multi thread
    Bonjour,

    Développant toujours mon lecteur audio je voulais ajouter une fonctionnalité qui est que l'utilisateur à l'aide d'un FolderBrowserDialog indique un dossier, et depuis ce dossier l'application va le traverser lui et ces sous-dossier à la recherche de fichiers musicaux. Ma fonction marche nickel. Cependant quand on est sur un petit dossier cela est assez rapide, mais à partir du moment où je choisis la racine du disque le temps d'attente est déjà beaucoup plus (trop?) long. L'interface n'a pas la main donc l'utilisateur doit attendre. De plus le temps que le chargement se fasse la FolderBrowserDialog ne disparait.

    Je connais les principes de bases du MultiThread mais je ne l'ai jamais appliqué en C# et encore moins sous WPF (même si je pense que c'est plus lié au C# qu'à WPF). Bref quoi qu'il en soit j'ai fait des recherches et des tests sans succés. J'ai trouvé ce sujet mais je n'ai pas beaucoup avancé.

    Je vous montre ma fonction de recherche:
    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
    //parcours les dossiers et sous dossier à la recherche de fichier à ajouter à la biblio
            private void searchFolder(string path)
            {
                //traverse tous les fichiers du dossier
                string[] File = Directory.GetFiles(path);
                foreach (string Fichier in File)
                {
                    if(this.AllowedExt.Contains(System.IO.Path.GetExtension(Fichier).ToLower()))
                    {
                        TagLib.File file = TagLib.File.Create(Fichier);
                        this.mainPlaylist.Add(
                            Fichier,
                            file.Tag.Title,
                            file.Tag.FirstAlbumArtist,
                            file.Tag.Album,
                            file.Properties.Duration.Minutes.ToString("00")+":"+file.Properties.Duration.Seconds.ToString("00")
                        );
                    }
                }
     
                //traverse les sous dossiers
                string[] Folder = Directory.GetDirectories(path);
                foreach (string Dossier in Folder)
                {
                    if((System.IO.File.GetAttributes(Dossier) & FileAttributes.System) != FileAttributes.System)
                        this.searchFolder(Dossier);
                }
            }
    Et l'appel ce fait ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private void button2_Click(object sender, RoutedEventArgs e)
            {
                FolderBrowserDialog FolderDialog = new FolderBrowserDialog();
                DialogResult result = FolderDialog.ShowDialog();
     
                if(result == System.Windows.Forms.DialogResult.OK)
                {
                    this.searchFolder(FolderDialog.SelectedPath);
                }
            }
    Ce que je voudrais c'est un peu d'aide, de manière assez simple pour débuter avec le multithreading en C#. Que vous puissiez m'aider à avancer là dessus car la c'est la panne sèche totale.

    Je vous remercie d'avance.

  2. #2
    Membre expérimenté

    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2009
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2009
    Messages : 215
    Par défaut
    Tu peux essayer de te documenter sur le composant BackgroundWorker (qui est dans la Toolbox de Visual Studio). Il devrait beaucoup t'aider à démarrer simplement dans le multithreading

  3. #3
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    BackgroundWorker en WPF ?
    J'aurai plus pensé à utiliser un Thread (un vrai, du System.Threading.Thread) pour faire le travaille et dans ce cas l'accès à un élément de l'interface doit se faire avec Dispatcher.Invoke

  4. #4
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Par défaut
    Citation Envoyé par smyley Voir le message
    BackgroundWorker en WPF ?
    Vivi, ca se fait aussi

  5. #5
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Au temps pour moi, je l'avais toujours vu qu'en WinForms

  6. #6
    Membre confirmé Avatar de Takumi
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2009
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 163
    Par défaut
    Merci pour vos réponses,

    Je vais me documenter sur les deux trucs, mais quel est le mieux à utiliser: la backgroundWorker ou un Thread de System.Threading?

    Ce que je recherches surtout c'est pouvoir faire en sorte que l'utilisateur puisse encore naviguer sur l'application malgrès que la recherche est en cours. De plus je voudrais pouvoir faire en sorte que mon thread qui s'execute en arrière-plan celui de la recherche) puisse accéder à un control de mon application (pour par exemple changer une valeur dans un label). Cependant j'avais lu sur un article qu'il était pas possible d'accéder à un control depuis un thread en arrière-plan mais qu'il existait des solution pour y arriver. Est-ce que je me trompe?

    Je vais déjà me documenter et faire quelques tests. Si je bloque je reviendrais demander votre aide.

  7. #7
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Ben soit Dispatcher.Invoke comme j'ai dit, soit tu regardes un peut l'utilisation du BackgroundWorker qui a été abordé des milliers de fois un peut partout sur le net ...

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    120
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : Luxembourg

    Informations forums :
    Inscription : Avril 2007
    Messages : 120
    Par défaut
    Coïncidence j'ai viens d'utiliser le BackgroundWorker hier dans une application WPF et cela fonctionne très bien. C'est pas exactement dans le même contexte que toi car c'est pour le lancement d'une animation en parallèle d'un chargement long mais le principe reste le même. En tout les cas étant habitué à l'utiliser en Winforms tu ne sera pas pas perturbé à l'utiliser en WPF, je te le recommande donc.

  9. #9
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Par défaut
    Citation Envoyé par smyley Voir le message
    Au temps pour moi, je l'avais toujours vu qu'en WinForms
    Oui mais bon, WPF ou Winforms, ca reste du .NET donc le composant existe toujours et il ne faut pas hésiter à l'utiliser

  10. #10
    Membre confirmé Avatar de Takumi
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2009
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 163
    Par défaut
    Bonsoir,

    Bon j'ai fait quelques test avec backgroundWorker, cela marche impec. Ma recherche se lance et j'arrive à reprendre la main sur mon interface. Par contre je rencontre le problème qui est que le thread en arrière plain ne peux accèder aux control du thread principale.

    Dans mon application j'ai une class qui s'appelle Playlist et comme son nom l'indique gère une playlist. Dans cette classe j'ai une fonction appelée Add. Celle-ci ajoute une chanson dans un fichier XML et par la même occasion l'ajoute à une collection. Voici le code la fonction:

    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
    //ajoute une chanson dans le fichier de playlist chargé
            public void Add(string path,string title,string artist,string album,string duration)
            {
                XmlElement newSong = file.CreateElement("song");
                newSong.SetAttribute("title", title);
                newSong.SetAttribute("artist", artist);
                newSong.SetAttribute("album", album);
                newSong.SetAttribute("duration", duration);
                newSong.SetAttribute("path", path);
                this.musicNode.AppendChild(newSong);
     
                //ajoute dans la collection
                this._songCollection.Add(new songData()
                {
                    SongName = title,
                    SongArtist = artist,
                    SongAlbum = album,
                    SongDuration = duration,
                    SongPath = path
                });
     
                this._Count++;
            }
    La collection en question est déclaré tel quelle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ObservableCollection<songData> _songCollection = new ObservableCollection<songData>(); //collection de chanson
    J'ai dans mon application une listView qui prend cette collection comme source. Et j'avais choisis une ObservableCollection car quand j'ajoutais des éléments à l'interieur je n'avais pas besoin de manuellement les ajouter au listView. Pour en revenir à mon histoire de backgroundWorker, le thread lancé en arrière plan fait une recherches de fichier, si il en trouve un qui correspond à ce que je cherche il l'ajoute donc à la playlist avec la fonction précédente. Cependant j'obtiens l'erreur suivante de la part du debugger:

    Ce type de CollectionView ne prend pas en charge les modifications de son SourceCollection à partir d'un thread différent du thread du Dispatcher.
    Et là voici la manière dont j'utilise mon backgroundWorker:

    D'abord les déclarations:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    private System.ComponentModel.BackgroundWorker bgwSearch = new System.ComponentModel.BackgroundWorker();
    this.bgwSearch.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bgwSearching);
    Puis voici la fonction exécuté en arrière plan:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private void bgwSearching(object sender,System.ComponentModel.DoWorkEventArgs e)
            {
                this.searchFolder((string)e.Argument);
                this.mainPlaylist.Save(this.LibraryPath);
            }
    Et là la fonction de recherches appelée par la précédente fonction:
    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
    //parcours les dossiers et sous dossier à la recherche de fichier à ajouter à la biblio
            private void searchFolder(string path)
            {
                //traverse tous les fichiers du dossier
                string[] File = Directory.GetFiles(path);
                foreach (string Fichier in File)
                {
                    if(this.AllowedExt.Contains(System.IO.Path.GetExtension(Fichier).ToLower()))
                    {
                        TagLib.File file = TagLib.File.Create(Fichier);
                        this.mainPlaylist.Add(
                            Fichier,
                            file.Tag.Title,
                            file.Tag.FirstAlbumArtist,
                            file.Tag.Album,
                            file.Properties.Duration.Minutes.ToString("00")+":"+file.Properties.Duration.Seconds.ToString("00")
                        );
                    }
                }
     
                //traverse les sous dossiers
                string[] Folder = Directory.GetDirectories(path);
                foreach (string Dossier in Folder)
                {
                    if((System.IO.File.GetAttributes(Dossier) & FileAttributes.System) != FileAttributes.System)
                        this.searchFolder(Dossier);
                }
            }
    Donc existe-il une solution pour pouvoir faire ce que je souhaite, malgré que ce soit appelé depuis un thread en arrière plan?

    Je vous remercie d'avance pour votre aide.

  11. #11
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Dispatcher.Invoke ?

  12. #12
    Membre confirmé Avatar de Takumi
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2009
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 163
    Par défaut
    Bonsoir,

    J'ai finalement réussi à faire ce que je veux.

    J'ai ma fonction de recherches qui tourne sur un autre Thread et quand j'ai besoin d'ajouter une musique j'utilise Dispatcher.Invoke de la façon suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
                            delegate()
                            {
                                TagLib.File file = TagLib.File.Create(Fichier);
                                this.mainPlaylist.Add(
                                    Fichier,
                                    file.Tag.Title,
                                    file.Tag.FirstArtist,
                                    file.Tag.Album,
                                    file.Properties.Duration.Minutes.ToString("00")+":"+file.Properties.Duration.Seconds.ToString("00")
                                );
                                this.labelSearch.Content = file.Tag.Title;
                            })
                        );
    Merci beaucoup

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

Discussions similaires

  1. Recherche de fichier dans un thread
    Par toma03 dans le forum Général Java
    Réponses: 1
    Dernier message: 24/09/2009, 14h14
  2. Réponses: 15
    Dernier message: 03/02/2009, 09h37
  3. [Tableaux] Fonction de recherche dans un fichier texte
    Par danathane dans le forum Langage
    Réponses: 6
    Dernier message: 09/07/2007, 15h45
  4. Créer une fonction de recherche multi début de mot
    Par Pakkaï dans le forum Général JavaScript
    Réponses: 29
    Dernier message: 29/03/2007, 17h16
  5. Réponses: 2
    Dernier message: 16/12/2006, 12h34

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