2012-06-29 45 views
0

我使用的是backgroundWorker做一個長期運行的操作:BackgroundWorker.ReportProgress()不更新財產和鎖定UI

BackgroundWorker backgroundWorker = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; 

backgroundWorker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
{ 

}; 

backgroundWorker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
{ 
    someViewModel.SomeProperty.Add((SomeObject)args.UserState); 
}; 

backgroundWorker.DoWork += delegate(object s, DoWorkEventArgs args) 
{ 
    someViewModel.SomeList.ForEach(x => 
    { 
     someViewModel.SomeInterface.SomeMethod(backgroundWorker, someViewModel, someViewModel.SomeList, x); 
    }); 
}; 

backgroundWorker.RunWorkerAsync(); 

然後在SomeInterface.SomeMethod

public void SomeMethod(BackgroundWorker backgroundWorker, SomeViewModel someViewModel//....) 
{ 
    //Filtering happens 

    backgroundWorker.ReportProgress(0, someObjectFoundWhileFiltering); 
} 

所以,當它來到:

backgroundWorker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
{ 
    someViewModel.SomeProperty.Add((SomeObject)args.UserState);//Adding the found object to the Property in the VM 
}; 

在線someViewModel.SomeProperty.Add((SomeObject)args.UserState);,設置上SomeProperty不是火警和UI只是鎖定。

我在做什麼錯?這是更新UI thread的正確方法嗎?

+0

把backgroundWorker.ReportProgress(0,someObjectFoundWhileFiltering);在DoWork()方法中。任何理由有被調用的方法? –

+0

SomeProperty的類型是什麼。你確定Add方法觸發一個事件(如NotifyPropertyChanged)。如何捕捉到someviewmodel對象中SomeProperty的變化? – Hyralex

+0

代碼看起來基本上OK,someViewModel.SomeProperty究竟是什麼? –

回答

0

發現周圍的工作現在:

DeepClone的object

backgroundWorker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
{ 
    ViewModel.SomeList = DeepClone<List<SomeObject>>(ViewModel.TempList); 
}; 

backgroundWorker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
{ 
    var item = DeepClone<SomeObject>((SomeObject)args.UserState); 

    ViewModel.TempList.Add(item); 
}; 

public static T DeepClone<T>(T obj) 
{ 
    using (var ms = new MemoryStream()) 
    { 
     var formatter = new BinaryFormatter(); 
     formatter.Serialize(ms, obj); 
     ms.Position = 0; 

     return (T)formatter.Deserialize(ms); 
    } 
} 
0

我希望你正在開發一個Windows窗體應用程序,如果你正在更新或發送一些值到窗體組件,你需要使用委託來將你的請求放在主線程Q中,試試這種方式可能會找到解決方案。

+1

它標記爲WPF – Paparazzi

0

對winforms控件的跨線程調用是危險的。他們可能導致不可預知的結果。 有時你會得到特殊的例外。有時用戶界面只是沒有重新繪製......在你的情況下,你正在掛。

爲了避免這種情況,請撥打電話到UI,如http://msdn.microsoft.com/en-us/library/ms171728.aspx中所述。 像這樣:

private void SetText(string text) 
    { 
     // InvokeRequired required compares the thread ID of the 
     // calling thread to the thread ID of the creating thread. 
     // If these threads are different, it returns true. 
     if (this.textBox1.InvokeRequired) 
     { 
      SetTextCallback d = new SetTextCallback(SetText); 
      this.Invoke(d, new object[] { text }); 
     } 
     else 
     { 
      this.textBox1.Text = text; 
     } 
    } 

注意,這梅託德必須付諸UI上下文,以便控制。 調用將請求放入UI消息隊列中,然後將其轉換並在UI線程中運行的UI消息循環處理。