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

 

posted @ 2017-05-10 10:29  Et0l1A  阅读(2208)  评论(0编辑  收藏  举报