2012-04-03 6 views
0

Zunächst einmal, Entschuldigung für die Länge der Frage.ProgressBar wird nicht auf dem Bildschirm aktualisiert, obwohl NotifyPropertyChanged ordnungsgemäß funktioniert

Ich aktualisiere eine Silverlight für Windows Phone 7 App, die derzeit Daten in mehreren XML-Dateien speichert. Ich aktualisiere die App, um eine CompactSQL DB zu verwenden, und ich muss die Daten von den XML-Dateien in die DB migrieren, wenn sie nach der Installation der neuen Version das erste Mal ausgeführt wird.

Ich möchte eine Fortschrittsanzeige (IsIndeterminate = false) zeigen den Benutzer den Fortschritt, wie jede Datei in die DB migriert wird (wie die Operation kann bis zu 2 Minuten dauern).

Das Problem ist, dass der Fortschrittsbalken auf dem Bildschirm trotz des NotifyProperyChanged-Ereignisses und des Aktualisierens des Werts der Leiste nicht aktualisiert wird (oder sogar auftaucht). Wenn ich den Wert in XAML einstelle, erscheint er in Ordnung (statisch - aber zumindest wird er auf dem Bildschirm gezeichnet).

Ich weiß nicht, warum die Fortschrittsanzeige überhaupt nicht auf dem Gerät angezeigt wird.

Mein INotifyChanged Setup

private int migrateCount; 
public int MigrateCount //Prop used for ProgressBar.Value 
{ 
    get 
    { 
     return this.migrateCount; 
    } 
    set 
    { 
     this.migrateCount = value; 
     NotifyPropertyChanged("MigrateCount"); 
    } 
} 

public int MigrateTotal { get; set; } //Prop used for ProgressBar.Maximum 

public void NotifyPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

void MainPage_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "MigrateCount") 
    { 
     ProBar.Maximum = MigrateTotal; //ProBar is the name of my ProgressBar 
     ProBar.Value = MigrateCount; 
    } 
} 

public event PropertyChangedEventHandler PropertyChanged; 

public MainPage() 
{ 
    this.PropertyChanged += new PropertyChangedEventHandler(MainPage_PropertyChanged); 
    ... 
} 

Aufruf der MigrateDB Methode in Loaded statt OnNavigatedTo weil OS jede App beendet, die zu lange dauert zu laden.

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 
    { 
     using (var store = IsolatedStorageFile.GetUserStoreForApplication()) 
     { 
      string[] dirs = store.GetDirectoryNames(); 
      if (dirs.Length > 1) //Checks to see if there's any data to migrate 
      { 
       MigrateDB(); 
       LoadData(); //Loads data from the DB once it's populated 
      } 
     } 

Diese Operation dauert ewig. Ungefähr 100 XML-Dateien pro Minute und ich erwarte, dass Benutzer zwischen 30 und 300 Dateien haben.

private void MigrateDB() 
{ 
    string[] DirList; 
    using (var store = IsolatedStorageFile.GetUserStoreForApplication()) 
    { 
     DirList = store.GetDirectoryNames("*"); 
     MigrateTotal = DirList.Length - 1; // -1 to account for the "Shared" Dir 
     foreach(...) 
     { 
      ... Does lots of IsoStore operations/XML serialising and DB updating 
      MigrateCount++; 
     } 
    } 
    ... 
}   

Antwort

2

hilft Ich habe es allen. Wie bereits erwähnt, wurde der UI-Thread blockiert und ich musste den CPU-intensiven Code in einen anderen Thread übertragen. Dadurch wurde der UI-Thread (Hauptthread) freigegeben, um die Fortschrittsleiste zu aktualisieren. Ich habe, dass die folgenden, indem

  • löschen alle INotifyPropertyChanged Code ändert.

  • Implementieren der BackgroundWorker-Klasse mithilfe dieses MSDN-Lernprogramms link.

  • ich den MigrateDB Methode Code innerhalb des BackgroundWorker.DoWork Ereignisses eingewickelt, und

  • meinen ProgressBar.Value im BackgroundWorker.ProgressChanged Ereignisse aktualisiert.

Dies ist meine letzte Arbeits Code mit Änderungen:

public partial class MainPage : PhoneApplicationPage 

private BackgroundWorker bw = new BackgroundWorker(); 

... 

public MainPage() 
    { 
     ... 

     bw.WorkerReportsProgress = true; 
     bw.WorkerSupportsCancellation = false; 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     ... 
    } 

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     LoadData(); //LINQ2SQL queries to display DB 
    } 

    void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     ProBar.Value = e.ProgressPercentage; 
    } 

void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     double total = 0; 
     double count = 0; 
     BackgroundWorker worker = sender as BackgroundWorker; 
     ... 
     foreach(...) 
     { 
      ... Does lots of IsoStore operations/XML serialising/DB updating 
      count++; 
      double cntr = count/total * 100; 
      worker.ReportProgress((int)cntr); 
     } 
    } 

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 
    { 
     ... 
     bw.RunWorkerAsync(); 
     ... 
    } 
0

Ich denke, es gibt ein Problem mit dem Threading. Wenn Sie den Fortschrittsbalken im Hauptprozess aktualisieren, ist es nicht möglich, ihn zu aktualisieren. Vielleicht wird es am Ende der Funktion aktualisiert, wenn alwais fertig ist. Ich weiß nicht, ob in Win-Telefon existiert aber versuchen, einen Hintergrund-Arbeiter

2

Das Problem ist gelöst, wenn Sie an einem anderen Thread arbeiten, wie die Progressbar seinen Fortschritt auf der Benutzeroberfläche zeichnen darf. Wenn Sie so im MainThread arbeiten, wie es aussieht, und Ihre Fortschrittsleiste darauf wartet, dass eine untätige Situation auf der Benutzeroberfläche gezeichnet werden darf, kann dies bei CPU-aufwändigen Methoden sehr lange dauern.

Multithreading

Die Antwort der Lösung ist einfach; Lasse deinen Datenbankleser in einen eigenen Thread fallen. Die Lösung als Software kann auch einfach sein, wenn Sie verwenden: ThreadStart(), um Ihren Leser in Thread und Dispatcher.BeginInvoke(), um die Fortschrittsbalken-Werte auf der GUI anzuzeigen. Siehe http://msdn.microsoft.com/en-us/library/system.threading.threadstart.aspx

http://www.devx.com/dotnet/Article/7003

Hoffnung, die

+0

Danke, ich dachte, es könnte etwas gewesen mit Threading zu tun habe ich aber mit einem Verlust von war, wie alles funktioniert. Am Ende habe ich es mit der BackgroundWorker-Klasse repariert, aber ohne deine Hilfe hätte ich es nicht gefunden. :) – Styff

Verwandte Themen