2012-04-03 39 views
0

首先,對於問題的長度感到抱歉。即使NotifyPropertyChanged正常工作,ProgressBar在屏幕上也不會更新

我正在更新Silverlight for Windows Phone 7應用程序,該應用程序當前將數據存儲在多個XML文件中。我正在更新應用程序以使用CompactSQL DB,並且在安裝新版本後首次運行時必須將XML文件中的數據遷移到數據庫中。

我想要一個進度條(IsIndeterminate = false)向用戶顯示每個文件遷移到數據庫時的進度(因爲該操作最多可能需要2分鐘)。

問題是,儘管NotifyProperyChanged事件觸發並正確更新了欄的值,進度條並未更新(甚至不顯示)。當我在XAML中設置值時,它看起來很好(靜態 - 但至少它是在屏幕上繪製的)。

我不知道爲什麼進度條根本沒有顯示在設備上。

我INotifyChanged設置

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); 
    ... 
} 

在調用加載的MigrateDB方法,而不是因爲的OnNavigatedTo終止OS任何應用程序時間過長加載。

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 
      } 
     } 

該操作需要很長時間。每分鐘大約有100個XML文件,我希望用戶有30到300個文件。

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++; 
     } 
    } 
    ... 
}   

回答

2

我得到它的所有工作。正如其他人所提到的,UI線程被阻塞,我需要將CPU密集的代碼轉移到另一個線程。這釋放了UI(主)線程來更新進度條。我做了以下更改

  • 刪除所有INotifyPropertyChanged代碼。

  • 按照此MSDN教程link實施BackgroundWorker類。

  • 我包裹BackgroundWorker.DoWork事件中的MigrateDB方法的代碼,並

  • 更新我在BackgroundWorker.ProgressChanged事件ProgressBar.Value。

這是我最後工作的代碼變化在於:

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

我認爲存在一個線索問題。如果您在主進程中更新進度欄,則無法更新它。也許它會在alwais完成時在函數結尾更新。 我不知道如果在贏得手機存在,但嘗試使用後臺工作人員

2

如果您將在另一個線程上工作,因爲進度條被允許在用戶界面上繪製他的進度,則問題得以解決。如果您正在使用MainThread,看起來像是這樣,並且您的進度條正在等待任何空閒情況被允許繪製到用戶界面,如果您有CPU消耗方法,那麼可能需要很長時間。

Multithreading

溶液的答案很簡單;將你的數據庫讀取器放到它自己的線程中 如果您使用: ThreadStart()將您的閱讀器放入Thread並且Dispatcher.BeginInvoke()在GUI上顯示進度欄值,則作爲軟件的解決方案也可以很容易。 見http://msdn.microsoft.com/en-us/library/system.threading.threadstart.aspx

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

希望幫助

+0

謝謝,我想這可能去過的是與線程,但是我是在這一切是如何工作的損失。我最終修復了BackgroundWorker類,但是如果沒有你的幫助,我不會找到它。 :) – Styff 2012-04-03 12:35:23

相關問題