2011-01-19 4 views
1

Je rencontre un problème pour que Parallel.ForEach fonctionne correctement. J'ai un contrôle listview qui charge un contenu de fichiers ou le contenu de plusieurs fichiers (chaque fichier représente un fichier journal) dans une riche zone de texte. Si tout avait fonctionné avec une boucle Foreach, il a décidé que l'opération parallèle réduirait le temps de chargement lors du chargement de plus de 100 fichiers.Parallel.ForEach et contrôle ListView

Voici le bloc de code que j'utilisais pour la boucle foreach. Comment puis-je faire fonctionner un Parallel.Foreach?

//Set cursor to WaitCursor Style 
this.Cursor = Cursors.WaitCursor; 

//Clear Messages RichTexBox 
this.rtbMessages.Clear(); 

//Loop through each selected file 
foreach (ListViewItem Item in lvMessageFiles.Items) 
{ 
    //Check if item is selected in the listview 
    if (Item.Selected && rtbMessages.TextLength < rtbMessages.MaxLength) 
    { 
     //Get Path to message file 
     filename = String.Format("{0}\\Data\\Log\\{1}.log", Global.AppPath, Item.SubItems[0].Text); 

     //Set Timeline Events calendar to selected items created date 
     cvTimeline.ShowDate(Convert.ToDateTime(lvMessageFiles.SelectedItems[0].SubItems[2].Text)); 

     //Check if file exists 
     if (File.Exists(filename)) 
     { 
      //streamreader to read the file 
      reader = new StreamReader(filename); 

      //to copy the read content in to richtextbox 
      string MessageContents = String.Format("{0}\n{1}\n", ("file:///" + filename.Replace(" ", "%20").Replace("\\", "/")), reader.ReadToEnd()); 
      rtbMessages.Text += MessageContents; 

      // closing streamreader 
      reader.Close(); 
     } 
    } 

} 

//Set cursor to WaitCursor Style 
this.Cursor = Cursors.Default; 

Répondre

0

Vous n'êtes pas autorisé à mettre à jour l'interface utilisateur à partir d'un fil non-UI, qui se visse dans un Parallel.ForEach sera évidemment. Au lieu de cela, utilisez la méthode Invoke pour définir le Text de rtbMessages et d'appeler cvTimeline.ShowDate

3

2 problèmes avec ce que vous faites.

1) avec ce code spécifique, vous essayez de modifier l'interface utilisateur à partir d'un fil d'arrière-plan qui n'est pas permis
2), ce scénario n'est pas un bon candidat pour la parallélisation de toute façon parce que vous êtes performace est « E/S lié "à un seul disque dur. si vous voulez accélérer le temps de chargement, diviser les fichiers sur plusieurs disques durs et parallélisation peut être utile

voir Is Parallel File.Read Faster than Sequential Read?

+0

bon point ... et puisque tous ces fichiers seront sur le même lecteur, le dossier même, et il n'y a pas de traitement de cpu-intensive de chaque fichier qu'il ne fait pas beaucoup de sens à paralléliser. –

+1

les deux bons points, aussi la commande n'est pas garantie dans Parallel.ForEach donc tous les fichiers de log seront dans un ordre quelque peu aléatoire – BrokenGlass

0

Je rencontre dejavu cette question ... En tout cas, jetez un oeil à ce blog article. C'est très simple à mon goût, mais fait exactement ce que vous essayez de réaliser - mettre à jour l'interface utilisateur tout en travaillant avec des collections simultanées en utilisant les nouveaux mécanismes parallèles .NET 4. Bien que pas ForEach mais tâche.

http://blogs.msdn.com/b/csharpfaq/archive/2010/06/18/parallel-programming-task-schedulers-and-synchronization-context.aspx