WPF-在TASK任務線程中改變綁定數據,在控件上同步顯示的解決方案。


一、 本文將解決什么問題?

 

本文將解決:在主線程綁定了數據源的前提下,工作線程改變數據源,數據源無法及時更新的問題。

 

二、問題是如何出現的?

 

UI控件屬於UI線程。所有的綁定關系,是沒辦法穿透線程的。所以,在子線程中改變數據源的步驟,必須要‘回到UI線程’來進行。

當然,這與要避免在UI線程里進行耗時操作 的理念並不沖突。我們只在改變數據時回UI線程,切記。

 

三、問題代碼

1. MainWindow.xaml:我在主窗體里存在以下這個控件

 1 <telerik:RadGridView x:Name="rgvSendHist" Margin="10,8,10,41" Style="{StaticResource RadGridViewClean}" EnableColumnVirtualization="True" EnableRowVirtualization="True" IsReadOnly="True" Grid.Row="1" SelectionChanged="rgvSendHist_SelectionChanged">
 2                         <telerik:RadGridView.Columns>
 3                             <telerik:GridViewDataColumn DataMemberBinding="{Binding DataSend}" Header="數據包發送內容" Width="3*"/>
 4                             <telerik:GridViewDataColumn DataMemberBinding="{Binding RecLength,Mode=OneWay}" Header="返回包長度" Width="3*"/>
 5                             <telerik:GridViewDataColumn DataMemberBinding="{Binding SuccStatus,Mode=OneWay}"  Header="是否成功" Width="3*"/>
 6                         </telerik:RadGridView.Columns>
 7 </telerik:RadGridView>

2. MainWindow.xaml.cs: 我在這里進行了綁定。

1 ObservableCollection<TaskOfMany> aMultiTaskList = new ObservableCollection<TaskOfMany>();
2 
3 this.rgvTaskList.ItemsSource = aMultiTaskList;

3.MainWindow.xaml.cs: 我在這里通過線程對aMultiTaskList進行了改變。

1 foreach(TaskOfMany aTaskOfMany in aMultiTaskList)
2 {
3     new Task(() =>
4     {
5         aTaskOfMany.StartScan();
6     }).Start();
7 }    

4.aTaskOfMany.StartScan內部:

1   this.TaskRunningStatus = TaskRunningStatusEnum.檢測中;

 

此時,這個變化根本無法同步到控件上。

 

四、解決方案

在aTaskOfMany.StartScan內部改變值時,使用以下語句,回到UI線程:

1 Application.Current.Dispatcher.Invoke((Action)(() =>
2 {
3     TaskRunningStatus = TaskRunningStatusEnum.檢測中;
4 }));

根據需要,你也可以使用BeginInvoke。至此,問題解決。

------------------------------------------------------------------------------------------------------------------------

分割線

------------------------------------------------------------------------------------------------------------------------

 

對於大多數人來說,使用了以上的解決方案,你的問題就已經解決了。但是,對我來說,以上的方案並沒有生效,讓我一度懷疑連‘回到UI線程’這個解決方案也解決不了我的問題。

經過定位,我發現問題出在了我對線程最大數量的控制上

1 ThreadPool.SetMaxThreads(10, 10);

設置了這句之后,貌似會影響invoke的創建(因為不能發起新線程了),所以就算用dispatcher回UI線程,也不能馬上生效。。。

 

感謝群里的尚哥、三台等大神。真心感謝。

 

2017-5-10 10:27

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM