2013-10-31 26 views
0

我在WPF UserControl上有一個BackgroundWorker。WPF Backgroundwork呃在DoWork事件上調用方法

 private readonly BackgroundWorker worker = new BackgroundWorker(); 

     public ucCustomer() 
     { 
      InitializeComponent(); 
      worker.DoWork += worker_DoWork; 
      worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
     } 
     private void worker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      // run all background tasks here 
      System.Threading.Thread.Sleep(10000); 
     } 

     private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      //update ui once worker complete his work 
     } 
     private void UserControl_Loaded(object sender, RoutedEventArgs e) 
     { 
      worker.RunWorkerAsync(); 
     } 

上面的代碼工作,用戶界面是響應該任務時的工作,但如果我的worker_DoWork()更改爲

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // run all background tasks here 
    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, 
     new Action(() => { 
     gridDataBind(); //A long data-mining task,using Dispatcher.Invoke() to access UI. 
    })); 
} 

private void gridDataBind() 
{ 
    SnEntities sn = new SnEntities(); 
    var customers = from c in sn.Customer select c; 
    dgCustomer.ItemsSource = customers.ToList(); 
} 

的UI是凍結,直到任務結束是。

它有什麼解決辦法嗎? 謝謝。

回答

1

嘗試設置的ItemsSource像下面的代碼:

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // run all background tasks here 
    e.Result = gridDataBind(); //A long data-mining task. 
} 

private IList<Customer> gridDataBind() 
{ 
    SnEntities sn = new SnEntities(); 
    var customers = from c in sn.Customer select c; 
    return customers.ToList(); 
} 

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     var customers = e.Result as IList<Customer>; 

     ObservableCollection<Customer> gridItemsSource = new ObservableCollection<Customer>(); 
     Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, 
          new Action(() => 
          { 
           dgCustomer.ItemsSource = gridItemsSource; 
          })); 

     foreach(var customer in customers) 
     { 
      Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, 
           new Action(() => 
           { 
            gridItemsSource.Add(customer); 
           })); 
     } 

    } 
+0

我可以只保留一個gridDatabind()方法,這樣我可以重用? – Cheung

+0

在這種情況下,您將不得不將我寫在RunWorkerCompleted中的代碼移動到您的gridDataBind()方法..這裏的實際問題是當您在ItemsControl中一次性設置itemsSource的itemsSource過多時,需要時間來渲染它們...所以我所做的就是先將ItemsSource設置爲ObservableCollection,然後逐個填充該集合..因此,您的視圖將不會被阻止 – Nitin

+0

我有10次感謝你說你:)靈感來自你的示例代碼和解釋。我很好理解問題發生的原因,因爲DataGrid必須呈現行項目並阻止UI。 – Cheung

0

存儲你的e.result在worker_RunWorkerCompleted在worker_DoWork數據和更新UI。 在這種情況下,當數據來自數據庫時,UI將是免費的。

0

試試這個,它應該幫助你

Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => gridDataBind();)); 
相關問題