2016-04-21 17 views
2

Es ist das erste Mal, dass ich Fortschrittsbalken in C# verwende. Mein Code kopiert einige Dateien und ich möchte den Fortschritt über einen Fortschrittsbalken anzeigen.Korrekte Verwendung des Fortschrittsbalkens

Die Sache, die ich an meinem Code nicht mag, ist, dass ich alle Dateien durchgehen muss, um das Maximum der Leiste einzustellen ... und später gehe ich denselben Prozess erneut durch, um die Dateien zu kopieren.

Ich kann einfach keinen Weg finden, einen reibungslosen Fortschritt in der Bar sicherzustellen, ohne dies zu tun. Ich muss zuerst den Max wissen, oder? Oder gibt es einen Trick?

-Code sieht wie folgt aus:

  • Einstellung der max:

    private static void setProgressBar(List<Source> sources, List<Destination> destinations) 
    { 
        progress.Value = 0; 
        progress.Maximum = 0; 
    
        foreach (var source in sources) 
        { 
         progress.Maximum += System.IO.Directory.GetDirectories(source.directory, "*", 
          SearchOption.AllDirectories).Count() * destinations.Count + 
          System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories).Count() * 
          destinations.Count; 
        } 
    
  • Kopieren der Dateien:

    public static void CopyData(List<Source> sources, List<Destination> destinations, RichTextBox box, ProgressBar bar) 
    { 
        log = box; 
        progress = bar; 
        setProgressBar(sources, destinations); 
    
        foreach (var source in sources) 
        { 
         foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", 
          SearchOption.AllDirectories)) 
         { 
          foreach (var destination in destinations) 
          { 
           logger(dirPath); 
           System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory)); 
          } 
         } 
    
         foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories)) 
         { 
          foreach (var destination in destinations) 
          { 
           logger(newPath); 
           File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true); 
          } 
         } 
        } 
    } 
    
  • Erhöhungsschritte der Fortschrittsbalken:

    private statische Void Logger (String-Ausgabe) { log.Text + = "Kopieren:" + Ausgabe + System.Environment.NewLine; log.SelectionStart = log.Text.Length; log.ScrollToCaret(); progress.Inkrement (1); }

So läuft ich den gleichen Code zweimal ... und ich weiß nicht wie das :)

Antwort

1

Ich sehe zwei Fehler in hier: Sie setzen nie Wert Ihrer progressbar ist im Copydata Methode und die zweite ist: Ihre CopyData-Methode wird Ihre Benutzeroberfläche einfrieren, bis die Methode fertig ist (und die Fortschrittsleiste wird von 0 bis 100% zu diesem Zeitpunkt springen).

Sie können Ihre CopyData-Methode in einen BackgroundWorker einfügen und ReportProgress aufrufen und den neuen Wert Ihrer Leiste im ReportProgress-Ereignis festlegen.

Hier ist ein Beispiel, wie es gemacht werden könnte. Statt static void Main(..) Ruf der Arbeiter aus, wo Sie Ihre Copydata-Methode

static void Main(string[] args) 
{ 
    System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker(); 
    worker.ProgressChanged += Worker_ProgressChanged; 
    worker.DoWork += Worker_DoWork; 

    //Do work 
    worker.RunWorkerAsync(); 
} 

private static void Worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    //Get Values 
    var source = null; 
    var destinations = null; 

    //CopyData Method 
    setProgressBar(sources, destinations); 
    foreach (var source in sources) 
    { 
     foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories)) 
     { 
      foreach (var destination in destinations) 
      { 
       logger(dirPath); 
       System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory)); 
       //Increase Value by 1 
       (sender as System.ComponentModel.BackgroundWorker).ReportProgress(1); 
      } 
     } 

     foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories)) 
     { 
      foreach (var destination in destinations) 
      { 
       logger(newPath); 
       File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true); 
       //Increase Value by 1 
       (sender as System.ComponentModel.BackgroundWorker).ReportProgress(1); 
      } 
     } 
    } 
} 

private static void Worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    if (e.ProgressPercentage == 1) 
    { 
     //If Value gets higher than Maximum it will cause an Exception 
     if (progress.Value < progress.Maximum) 
      progress.Value += 1; 
    } 
} 

private static void setProgressBar(List sources, List destinations) 
{ 
    progress.Value = 0; 
    progress.Maximum = 0; 
    foreach (var source in sources) 
    { 
     foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories)) 
     { 
      //Simplified 
      progress.Maximum += destinations.Count; 
     } 

     foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories)) 
     { 
      //Simplified 
      progress.Maximum += destinations.Count; 
     } 
    } 
} 
+0

Vielen Dank für Ihre Antwort beginnen würde, Zuerst gibt man fehlte Methode so konnte man nicht sehen, dass ich erhöhen tun den Wert des Fortschrittsbalken in der ' Logger (newPath) 'Methode. So springt es nicht von 0 bis 100. Zweitens, dies über einen BackgroundWorker zu tun, verbessert nicht die Situation, dass der leistungsstärkste Code (der, den Sie vereinfacht haben) zweimal ausgeführt wird! Stellen Sie sich vor, es gibt 2000 Verzeichnisse, die das Programm 1.5 verlangsamen würde. - 2 Mal. Ich suche nach einer Möglichkeit, das zu verbessern. Ich weiß nicht, ob es möglich ist, aber –

+1

Ich lese ein paar mehr Artikel über Hintergrundarbeiter und ich sah, dass diese in verschiedenen Threads laufen. Also ich denke deine Antwort hilft mir aus! –

+0

Froh, das zu hören :) über die andere Frage mit dem leistungsintensiven Code. Sie könnten die Verzeichnisse bis zu dem Punkt, an dem Sie Ihre Dateien schreiben, ignorieren und prüfen, ob das Verzeichnis der Zieldatei existiert. wenn nein -> erstelle es. Wäre die einzige Idee, die ich bisher über diesen Teil der Frage habe. –

Verwandte Themen