Ca fige ... faut il bosser en asynchrone ?

Résolu
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014
-
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014
-
Salut !

Voici un petit code qui parcours un dossier de MP3 (sous dossiers compris) et qui crée un fichier txt qui liste le nom complet du titre, son répertoire, genre et album (tags).
Selon la taille du dossier, ça devient assez long.
J'ai un problême : le form fige, les labels ne se mettent pas à jour et la barre de chargement ne marche plus lorsque lorsque l'on perd le focus du form et qu'on le reprend.
J'ai lu et + ou - compris le tuto sur threads/synchrone/asynchrone.
Mais est ce que si je modifie mon code de manière à excecuter quelque chose en asynchrone, cela va régler mon problême ? Et dans ce cas, que dois excecuter en asynchrone ? ou peut être des threads ?
(Pour ceux que ça interesserait et qui voudrais la suite du code (getRepertoire, getGenre et getAlbum)... dites le ...)

private
void CreerFichierTXT(
string CheminBibliotheque){

ArrayList Rep =
new
ArrayList();

ArrayList NbTitres =
new
ArrayList();getListeRepertoires(CheminBibliotheque, Rep, NbTitres);

Barre.Minimum = 1;

Barre.Step = 1;

for (int i 0; i < NbTitres.Count; i++)Barre.Maximum Barre.Maximum + System.

Convert.ToInt32(NbTitres[i]);

int NumTitre = 0;

StreamWriter TXT =
new
StreamWriter(CheminBibliotheque +
"/Bibliotheque.txt",
false,
ASCIIEncoding.Default);

for (
int i = 0; i < Rep.Count; i++){

foreach (
string S
in
Directory.GetFiles(Rep[i].ToString(),
"*.mp3", System.IO.
SearchOption.TopDirectoryOnly)){

NumTitre++;

lNbTitres.Text =

"Titre nø" + NumTitre.ToString() +
"/" + Barre.Maximum.ToString();lNomTitre.Text = S;

Barre.PerformStep();

TXT.WriteLine(

"Titre|" + S);TXT.WriteLine(

"Repertoire|" + Rep[i].ToString().Substring(CheminBibliotheque.Length + 1, Rep[i].ToString().Length - (CheminBibliotheque.Length + 1)));TXT.WriteLine(

"Genre|" + getGenre(S));TXT.WriteLine(

"Album|" + getAlbum(S));

this.Refresh();}

}

TXT.Close();}

MERCI D'AVANCE ...

MMN

15 réponses

Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
Voila, sans tester (vu qu'il me manque tes méthodes et que j'ai la flemme :p ), je dirais que ca donne ca :

<hr />

private
delegate
void
ChangeLabelDelegate(
Label label,
string text);

private
delegate
void
IncreaseProgressBarDelegate();

private
delegate
void
SetMaximumDelegate(
int value);

private
ArrayList Rep =
new
ArrayList();

private
ArrayList NbTitres =
new
ArrayList();

private
void ChangeLabel(
Label label,
string text)
{
   label.Text = text;
}

public
void IncreaseProgressBar()
{

   this.Barre.Increment(1);
}

public
void SetMaximum(
int value)
{

   this.Barre.Maximum += value;
}

private
void LaunchProcess(
object data)
{

   string CheminBibliotheque = (
string)data;
   getListeRepertoires(CheminBibliotheque, Rep, NbTitres);

   this.Invoke(
new
SetMaximumDelegate(SetMaximum), NbTitres.Count);

   int NumTitre = 0;

   using (
StreamWriter TXT =
new
StreamWriter(CheminBibliotheque +
"/Bibliotheque.txt",
false,
ASCIIEncoding.Default))
   {

      for (
int i = 0; i < Rep.Count; i++)
      {

         foreach (
string S
in
Directory.GetFiles(Rep[i].ToString(),
"*.mp3", System.IO.
SearchOption.TopDirectoryOnly))
         {
            NumTitre++;

            IAsyncResult iasync1 =
this.BeginInvoke(
new
ChangeLabelDelegate(ChangeLabel),
new
object[] { lNbTitres,
string.Format(
"Titre nø {0} / {1}", NumTitre, Barre.Maximum) });

            IAsyncResult iasync2 =
this.BeginInvoke(
new
ChangeLabelDelegate(ChangeLabel),
new
object[] { lNomTitre, S });

            IAsyncResult iasync3 =
this.BeginInvoke(
new
IncreaseProgressBarDelegate(IncreaseProgressBar));
            TXT.WriteLine(
"Titre|" + S);
            TXT.WriteLine(
"Repertoire|" + Rep[i].ToString().Substring(CheminBibliotheque.Length, Rep[i].ToString().Length - (CheminBibliotheque.Length + 1)));
            TXT.WriteLine(
"Genre|" + getGenre(S));
            TXT.WriteLine(
"Album|" + getAlbum(S));

            this.EndInvoke(iasync1);

            this.EndInvoke(iasync2);

            this.EndInvoke(iasync3);
         }
      }
   }
}
<hr />
que tu appeles ainsi :

<hr />Thread thread =
new
Thread(
new
ParameterizedThreadStart(LaunchProcess));
thread.Start(TonChemin
);
<hr />
Ensuite, a toi d'optimiser ton code, gerer les exceptions, etc.
Je t'ai juste donné de quoi comprendre comment on utilise Threads + delegués synchrones / asynchrones.

J'ai enlevé le code qui définit le minimum et le step de ta barre, il faut que tu le mettes dans le code ou tu initialises tes controles plutot.

Mx
MVP C# 
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Membre
Dernière intervention
14 février 2014
38
oui... quand les traitements sont long il FAUT bosser en Asynchrone.

donc, tout ce qui est recherche, téléchargement, traitement...

Sébastien FERRAND (
blog)
Consultant Indépendant
[Microsoft MVP Visual C#]
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Est ce que tu pourrais préciser un petit peu ta réponse. dans mon code, qu'est ce qu'il faudrait que j'appelle en asynchrone ?

MMN
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
Salut,

Appelle toute ta méthode dans un Thread différent, et change toutes les instuctions qui modifient les propriétés de tes controles (ProgressBar, Labels), afin d'eviter le CrossThreading, avec la meme procédure que celle qu'on t'a donné dans un précédent topic

Mx
MVP C# 
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

...  Jy ArRIvE PA !

Je bonderais le serveur si je vous listais mes erreurs.
MorpionMx> Peut tu me modifier un petit peu ce code  ?

MMN
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
Ok, ca arrive

Mx
MVP C# 
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Ok merci beaucoup.


Finalement je suis arrivé a enlever mes erreurs et a le faire marcher tout seul, mais j'ai fait beaucoup de bidouillage (c'est pas beau à voir). Tu ne l'a cependant pas fait pour rien parce qu'au moins ca me permet d'apprendre un peu.

Merci les admin CS sources, vous êtes des dieux !  (sans faire de lèche ...)

MMN
Messages postés
1642
Date d'inscription
samedi 6 novembre 2004
Statut
Modérateur
Dernière intervention
28 avril 2011
3
Salut,

Un peu en retard tout de même, je précise qu'il y dans le framework .NET2 un joli petit composant pour l'Asynchrone nommé BackgroundWorker qui englobe tout ça et qui évite d'avoir à manipuler à la main les threads, invoke, IAsyncResult, etc...
(très très pratique )

Voilà c'est tout

A++ et bonne continuation

<hr width="100%" size="2" />Nurgle (Antoine)
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
Pourtant c'est rigolo de s'amuser avec les Threads ^^

Mx
MVP C# 
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Si t'y a le goût, je ne serait pas contre un petit exemple avec le backgrouder worker

MMN
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
Il y a un exemple dans le lien que Nurgle fournit ;)

Mx
MVP C# 
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Membre
Dernière intervention
20 juin 2013
59
Le backgroundWorker ne fait pas tout, il a ces limites...
Je ne sais pas pourquoi, mais j'utilise rarement cet object, je suis toujours avec les Threads moi ;-)

<hr size="2" />VC# forever
Messages postés
1642
Date d'inscription
samedi 6 novembre 2004
Statut
Modérateur
Dernière intervention
28 avril 2011
3
Bof, il a ses limites en effet
Mais tant qu'on ne fait pas de choses trop compliquées, il est utile.
Je dirais que tant qu'on ne manipule qu'un seul autre Thread, le BackgroundWorker suffit largement, d'autant qu'il supporte l'annulation et qu'il peut facilement rapporter sa progression.

Enfin bon, c'est un controle pour les flemmards quoi (comme moi) ;-)
(voir des IAsyncResult et des Invoke de partout me donne des boutons...)

<hr width="100%" size="2" />Nurgle (Antoine)
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Membre
Dernière intervention
30 octobre 2008
55
C'est vrai que IAsyncResult, BeginInvoke, etc, ca semble etre des termes barbares  Et ca semble repoussant
Mais bon, une fois qu'on a pris l'habitude de s'en servir, ca pose plus de soucis

Mx
MVP C# 
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Moi je trouve ca tout simplement génial les threads.

MMN