2009-07-28 22 views
9

Ich arbeite in C# und WPF, sehr neu für beide.Wie zeige ich den Fortschritt während einer aktiven Schleife an?

Ich habe eine Schleife, die viele Daten von einer externen Quelle liest. Der Vorgang dauert ungefähr 20 Sekunden und ich möchte dem Benutzer den Fortschritt anzeigen. Ich brauche keine ausgefeilten Fortschrittsbalken, daher habe ich meinen Fortschritt in einem Etikett mit der Bezeichnung "Schritt 1/1000" und dann "Schritt 2/1000" usw. dargestellt.

Mein Code sieht ungefähr so ​​aus dies:

// "count" is the number of steps in the loop, 
// I receive it in previous code 

String countLabel = "/"+count.ToString(); 

for (i = 0; i < count; i++) 
{ 
    ... do analysis ... 
    labelProgress.Content = "Step "+i.ToString()+countLabel 
} 

jedoch während dieser Analyse ist der Bildschirm „stecken“ und die Fortschritte zeigen, nicht so voran. Ich verstehe dieses Verhalten aus meiner Vergangenheit in C++, wo ich wahrscheinlich einen separaten Thread hätte, der einen Fortschrittsbalken zeigt, der Benachrichtigungen von der Schleife empfängt, oder irgendeine Art von Repaint/Refresh, oder das Fenster/App dazu zwingt, seine Nachrichtenwarteschlange zu verarbeiten.

Was ist der richtige Weg, um es in C# zu tun? Ich bin nicht auf das Etikett gebunden, so dass, wenn es ein einfaches Statusleiste Popup-Fenster kann ich anstelle diesem Label verwendet es auch groß sein würde ...

Dank

+0

Diese für Sie Hilfe kann , ** 100% getestet ** http://stackoverflow.com/a/42995210/6863414 –

Antwort

11

das Werk zu einem BackgroundWorker bewegen und Verwenden Sie die Methode.

for (i = 0; i < count; i++) 
{ 
    ... do analysis ... 
    worker.ReportProgress((100 * i)/count); 
} 

private void MyWorker_ProgressChanged(object sender, 
    ProgressChangedEventArgs e) 
{ 
    taskProgressBar.Value = Math.Min(e.ProgressPercentage, 100); 
} 
+0

Ist das Thread-sicher? –

+1

Ja, sollte es sein. Ihr Hintergrund-Worker ist nur in einem Thread, das Update der Fortschrittsbalken ist nur auf dem UI-Thread. Jeder Thread außer dem UI-Thread löst eine Ausnahme aus, wenn er versucht, den Wert zu aktualisieren. So ist die Threadsicherheit mit dieser Methode garantiert. – user7116

2

Die Benutzeroberfläche ist nicht aufgrund der Tatsache, aktualisiert, dass Ihr aktueller Thread eine höhere Priorität als die UI-Thread hat, die letztlich das Etikett festgelegt werden;). Bis dein Thread fertig ist, wird dein Label am Ende aktualisiert.

Glück für uns gibt es eine Dispatcher Eigenschaft auf jedem WPF-Steuerelement, das Sie einen neuen Thread mit einer anderen Priorität feuern kann ..

labelProgress.Dispatcher.Invoke(DispatcherPriority.Background, 
        () => labelProgress.Content = string.Format("Step {0}{1}", i, countLabel)); 

Dieses Feuer einen Thread im Hintergrund und würde den Job erledigt! Sie können auch andere Optionen DispatcherPriority

PS versuche ich nahm auch die Freiheit, eine anonyme Methode hinzufügen und Ihre Zeichenfolge beheben Parsen etwas .. hoffe es Ihnen nichts ausmacht ..

3
//Create a Delegate to update your status button 
    delegate void StringParameterDelegate(string value); 
    String countLabel = "/" + count.ToString(); 
    //When your button is clicked to process the loops, start a thread for process the loops 
    public void StartProcessingButtonClick(object sender, EventArgs e) 
    { 
     Thread queryRunningThread = new Thread(new ThreadStart(ProcessLoop)); 
     queryRunningThread.Name = "ProcessLoop"; 
     queryRunningThread.IsBackground = true; 
     queryRunningThread.Start(); 
    } 

    private void ProcessLoop() 
    { 
     for (i = 0; i < count; i++) 
     { 
      ... do analysis ... 
      UpdateProgressLabel("Step "+i.ToString()+countLabel); 
     } 
    } 

    void UpdateProgressLabel(string value) 
    { 
     if (InvokeRequired) 
     { 
      // We're not in the UI thread, so we need to call BeginInvoke 
      BeginInvoke(new StringParameterDelegate(UpdateProgressLabel), new object[] { value }); 
      return; 
     } 
     // Must be on the UI thread if we've got this far 
     labelProgress.Content = value; 
    } 
+0

BackgroundWorker wird zur Verfügung gestellt, damit Sie nicht mit der ganzen Unordnung eines Threads fertig werden müssen. – user7116

+0

@sixlettervariables Der Wert dieser Methode ist, dass Sie mehr Flexibilität als nur eine Ganzzahl zurück an den Aufrufer übergeben können - Sie können alles tun (z. B. eine Statusmeldung zurückgeben) – ean5533

Verwandte Themen