2016-08-03 20 views
1

Ich habe über zwei Tage nach einer Lösung für dieses Problem gesucht und habe mich schließlich dazu entschieden, diese Frage zu stellen. Ich habe VIELE relevante Themen gefunden, aber keine von ihnen scheint mein Problem zu lösen. Zuletzt habe ich alle aufgelisteten Lösungen ausprobiert here.Spezifischer Anwendungsfall für Hintergrundaktualisierung Fortschrittsbalken

Hintergrund Info: Ich habe eine Klasse, die eine riesige Menge von Daten verarbeitet. Die Klasse heißt Traverse. Es gibt eine Klassenmethode namens DoFullTraverse (Traverse.DoFullTraverse), die einen vollständigen Polygonzug ausführt, der (je nach Benutzereingabe) bis zu 30 Sekunden dauern kann. Ich arbeite in WPF, MVVM-Muster. Ich möchte eine Statusleiste auf der GUI für den Fortschritt der DoFullTraverse aktualisieren. Ich berechne zu Beginn der Funktion die genaue Anzahl der für die Berechnung benötigten Schleifen und inkrementiere dann einen Schleifenzähler. Jedes Mal, wenn es ein weiteres 1/100 erreicht, inkrementiere ich den Fortschrittsbalken um 1. Mein Fortschrittsbalken (in xaml) ist an eine Eigenschaft in meiner VM mit der Bezeichnung gebunden.

jüngste Versuch: ich versucht habe, 100 verschiedene Lösungen, aber mein letzter Versuch, sieht wie folgt aus:

private void runTraverseAndUpdateBar() 
{ 
    var worker = new BackgroundWorker(); 
    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_Complete); 
    worker.RunWorkerAsync(); 
    while (!ThreadCheck) 
    { 
     Thread.Sleep(500); 
    } 
} 
void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var worker = sender as BackgroundWorker; 
    for (int i = 0; i < 36; i++) 
    { 
     Thread.Sleep(500); 
     PBarV += 3; 
    } 
    e.Result = true; 
} 
void worker_Complete(object sender, RunWorkerCompletedEventArgs e) 
{ 
    ThreadCheck = true; 
} 

Ich glaube, dass ich im Grunde bin Missverständnis, wie der Hintergrund Arbeiter funktionierts.

Das Hauptproblem: Ich kann diese Methode erhalten, um gut zu funktionieren, wenn ich die Funktion in den Hintergrundarbeiter werfe und wie gewohnt fortfahre. Das Problem ist, ich brauche die Daten von dieser Funktion, bevor mein Programm fortfährt. Daher brauche ich es linear auszuführen, aber die Statusleiste immer noch korrekt zu aktualisieren.

Wenn jemand etwas Licht auf das, was ich vermisse, werfen oder mich sogar in die richtige Richtung schubsen kann, würde ich es sehr schätzen.

Edit: Dies ist kein Duplikat. Der von Ihnen bereitgestellte Beitrag behandelt nicht das Problem der linearen Ausführung und wartet darauf, dass der Hintergrundarbeiter abgeschlossen wird, bevor er fortfährt.

Edit 2: (A Per @Clemens Request)

Ich brauche den Hintergrund Arbeiter Arbeit abgeschlossen ist, bevor das Hauptprogramm wird fortgesetzt. Ich führe den rechenintensiven Prozess speziell im Hintergrundarbeiter aus, damit der Fortschrittsbalken aktualisiert werden kann. Aber, bevor das Hauptprogramm fortfahren kann, brauche ich die Informationen von Traverse.DoFullTraverse();

Um SEHR spezifisch zu sein. Das Hauptprogramm sollte alle Ausführung anhalten (andere als Statusleiste Aktualisierung), bis der Hintergrund Arbeiter hat Traverse.DoFullTraverse(); abgeschlossen

+0

Erklären Sie "lineare Ausführung" und wie ein BackgroundWorker "vor dem Fortfahren" abschließen würde. IMO, das macht keinen Sinn. Rufen Sie 'ReportProgress' in erwarteten/erforderlichen/geeigneten Intervallen auf. – Clemens

+0

Nochmals bearbeitet. Hoffentlich kannst du das verstehen. – Kikootwo

+0

macht immer noch keinen Sinn. Die Idee eines BackgroundWorker ist * nicht * das Hauptprogramm bis zum Abschluss zu halten. Es läuft parallel (bis es abgeschlossen ist) und kann ab und zu den Fortschritt mit seiner 'ReportProgress'-Methode melden. Verwenden Sie keinen BackgroundWorker, wenn das Hauptprogramm nicht weiter ausgeführt werden soll. – Clemens

Antwort

1

Hier ist ein triviales Beispiel Sie spielen, um und zu Ihrer Ansicht Modell anwenden. Es ist wichtig, Prototypen zu verwenden, um Code zu erstellen und zu lernen, wie er funktioniert, um ihn auf eine größere und komplexere Anwendung anzuwenden.

Bitte beachten Sie, dass das Beispiel keine trivialen Dinge wie die Implementierung von INotifyPropertyChanged und ICommand enthält - diese sind einfach zu machen.

Beachten Sie auch die Kommentare innerhalb TraverseYo. Insbesondere diejenigen, die Ihnen sagen, auf welchem ​​Thread Sie gerade sind. Es ist wichtig, den Ablauf der Ausführung in Threads zu verstehen, damit dies richtig funktioniert.Wenn Sie nicht wissen, in welchem ​​Thread Sie sich befinden, rufen Sie einfach die ApartmentState des aktuellen Threads. Wenn es sich um eine STA handelt, liegt die Wahrscheinlichkeit am höchsten im UI-Thread.

public class LongLastingWorkViewModel : INotifyPropertyChanged 
{ 
    public bool Busy 
    { 
     // INotifyPropertyChanged property implementation omitted 
    } 
    public double PercentComplete 
    { 
     // INotifyPropertyChanged property implementation omitted 
    } 

    public ICommand PerformWork { get; set; } 

    public LongLastingWorkViewModel() 
    { 
     // delegated ICommand implementation omitted--there's TONS of it out there 
     PerformWork = new DelegatedCommand(TraverseYo); 
    } 

    private void TraverseYo() 
    { 
     // we are on the UI thread here 
     Busy = true; 
     PercentComplete = 0; 
     Task.Run(() => { 
      // we are on a background thread here 
      // this is an example of long lasting work 
      for(int i = 0; i < 10; i++) 
      { 
       Thread.Sleep(10 * 1000); // each step takes 10 seconds 

       // even though we are on a background thread, bindings 
       // automatically marshal property updates to the UI thread 
       // this is NOT TRUE for INotifyCollectionChanged updates! 
       PercentDone += .1; 
      } 
      Busy = false;    
     }); 
} 

können Sie binden Busy zu einem Overlay blockiert alle UI während der Ausführung ausgeführt wird, binden PercentComplete an einen Fortschrittsbalken und PerformWork auf eine Taste.