2013-07-30 5 views
0

J'ai une application qui lit des fichiers, chaque fichier a son propre temps d'exécution, je viens d'ajouter mes fichiers dans mon Listview et cliquez sur le bouton de lecture.Tâche Parallèle.PourCe rapport au milieu du travail

ceci est ma fonction qui a reçu la liste en entrée, cette liste inclut tous mes fichiers et parce que je veux l'option d'exécuter plus de 1 fichier simultanément je peux contrôler le nombre de fichiers parallèles:

public void doWork(IEnumerable<string> source, int parallelThreads) 
{ 
    _tokenSource = new CancellationTokenSource(); 
    var token = _tokenSource.Token; 
    Task.Factory.StartNew(() => 
    { 
     try 
     { 
      Parallel.ForEach(source, 
       new ParallelOptions 
       { 
        MaxDegreeOfParallelism = parallelThreads //limit number of parallel threads 
       }, 
       file => 
       { 
        if (token.IsCancellationRequested) 
         return; 
        //do work... 
       }); 
     } 
     catch (Exception) 
     { } 

    }, _tokenSource.Token).ContinueWith(
      t => 
      { 
       //finish... 
      } 
     , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread 
     ); 
} 

quand fichier fini en cours d'exécution d'un autre fichier (au cas où je choisirais de lire plusieurs fichiers simultanément) et dans le cas où je voudrais mettre à jour mon interface utilisateur ce fichier spécifique, comment puis-je savoir en temps réel début du fichier?

+0

Il suffit de déclencher l'événement chaque fois qu'une tâche se termine. Assurez-vous simplement de 'Invoke' dans le thread d'interface utilisateur avant de mettre à jour l'interface utilisateur. – Pete

+0

Puis-je avoir un exemple? (je suis un nouveau développeur) – user2214609

Répondre

0

Je ne suis pas en mesure de tester cela avec un compilateur et je n'ai pas fait WinForms depuis un moment, donc il peut y avoir quelques erreurs de syntaxe mineures ici, mais cela devrait vous aider à aller dans la bonne direction:

... In your form code ... 

ClassNameHere myOb = new ClassNameHere(); 
myOb.FileComplete += new FileCompleteHandler(FileDone); 

... 

public void FileDone(object sender, EventArgs e) 
{ 
    if (InvokeRequired) 
    { 
     Invoke(new FileCompleteHandler(FileDone), new object[] { sender, e }); 
     return; 
    } 

    ... update UI here ... 
} 

Ensuite, dans votre classe qui effectue le travail réel (vous pouvez, bien sûr, appeler la classe ce que vous voulez). Que diriez-vous de créer un événement auquel l'UI peut s'abonner?

public delegate void FileCompleteHandler(object sender, EventArgs e) 
public class ClassNameHere 
{ 

    protected virtual void OnFileComplete() 
    { 
     FileCompleteHandler handler = FileComplete; 
     if (handler != null) 
     { 
      handler(this, EventArgs.Empty); 
     } 
    } 

    public void doWork(IEnumerable<string> source, int parallelThreads) 
    { 
     _tokenSource = new CancellationTokenSource(); 
     var token = _tokenSource.Token; 
     Task.Factory.StartNew(() => 
     { 
      try 
      { 
       Parallel.ForEach(source, 
        new ParallelOptions 
        { 
         MaxDegreeOfParallelism = parallelThreads //limit number of parallel threads 
        }, 
        file => 
        { 
         if (token.IsCancellationRequested) 
          return; 
         //do work... 

         // This is where we tell the UI to update itself. 
         OnFileComplete(); 
        }); 
      } 
      catch (Exception) 
      { } 

     }, _tokenSource.Token).ContinueWith(
       t => 
       { 
        //finish... 
       } 
      , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread 
      ); 
    } 

    public event FileCompleteHandler FileComplete; 
}