WPF或WinFrom跨线程跨类使用控件-Dispatcher.Invoke方法

很多小伙伴对“跨线程或跨类”使用WPF或WinFrom页面的控件不太明白,奉上一段小案例供参考(下面为WPF代码,WinFrom同理):

注:在WPF或WinFrom中,UI元素只能由其主线程来操作,其他任何线程都不可以直接操作UI,可以使用Dispatcher.Invoke(同步操作)或Dispatcher.BeginInvoke (异步操作)来操作。

1.xaml页面代码:

 1 <Window
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WpfPaging"
 7         xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" x:Class="WpfPaging.测试跨线程跨类调用控件"
 8         mc:Ignorable="d"
 9         Title="MainWindow" Height="700" Width="1000" Loaded="Window_Loaded">
10     <Grid>
11         <DataGrid HorizontalAlignment="Left" Height="623" Margin="10,10,0,0" VerticalAlignment="Top" Width="972" Name="dgtext"  CanUserAddRows="True" AutoGenerateColumns="True">
12             <DataGrid.Columns>
13                 <DataGridTextColumn Header="选中" Width="35" />
14                 <DataGridTextColumn Header="公司名称" Width="80" Binding="{Binding 公司名称, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
15                 <DataGridTextColumn Header="姓名" Width="80" Binding="{Binding 姓名, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
16                 <DataGridTextColumn Header="年龄" Width="80" Binding="{Binding 年龄, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
17                 <DataGridTextColumn Header="职务" Width="80" Binding="{Binding 职务, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
18             </DataGrid.Columns>
19         </DataGrid>
20         <Button Content="添加" HorizontalAlignment="Left" Margin="10,638,0,0" VerticalAlignment="Top" Width="75" Name="btnAdd" Click="BtnAdd_Click" RenderTransformOrigin="1.68,0.545"/>
21         <Button Content="保存" HorizontalAlignment="Left" Margin="121,638,0,0" VerticalAlignment="Top" Width="75" Name="btnSave" Click="btnSave_Click" RenderTransformOrigin="1.68,0.545"/>
22         <Button Content="删除" HorizontalAlignment="Left" Margin="236,638,0,0" VerticalAlignment="Top" Width="75" x:Name="btnDele" Click="btnDele_Click" RenderTransformOrigin="1.68,0.545"/>
23         <Button Content="跨线程调用控件" HorizontalAlignment="Left" Margin="334,638,0,0" VerticalAlignment="Top" Width="113" x:Name="btn1" Click="btn1_Click" RenderTransformOrigin="1.68,0.545"/>
24         <Button Content="跨类调用控件" HorizontalAlignment="Left" Margin="458,638,0,0" VerticalAlignment="Top" Width="97" x:Name="btn2" Click="btn2_Click" RenderTransformOrigin="1.68,0.545"/>
25         <Button Content="跨线程跨类调用控件" HorizontalAlignment="Left" Margin="566,638,0,0" VerticalAlignment="Top" Width="140" x:Name="btn3" Click="btn3_Click" RenderTransformOrigin="1.68,0.545"/>
26     </Grid>
27 </Window>

xaml.cs代码

 1 using System.Collections.Generic;
 2 using System.Threading;
 3 using System.Windows;
 4 using System.Windows.Threading;
 5 using WpfPaging.NewFolder1;
 6 
 7 namespace WpfPaging
 8 {
 9     // 声明一个委托
10     //public delegate void ChangeForm1TextBoxValue(string txt);
11     /// <summary>
12     /// MainWindow.xaml 的交互逻辑
13     /// </summary>
14     public partial class 测试跨线程跨类调用控件 : Window
15     {
16         #region 变量
17         // 委托事件
18         //public static event ChangeForm1TextBoxValue ChangeTextBoxValue;
19         #endregion
20 
21         public 测试跨线程跨类调用控件()
22         {
23             InitializeComponent();
24         }
25 
26         private void Window_Loaded(object sender, RoutedEventArgs e)
27         {
28             // 获取这些新添加的记录
29             List<Information> lstInformati = new List<Information>();
30             Information information = new Information();
31             information.公司名称 = "公司名称0";
32             information.姓名 = "姓名0";
33             information.年龄 = "年龄0";
34             information.职务 = "职务0";
35             lstInformati.Add(information);
36             dgtext.ItemsSource = lstInformati;
37             dgtext.Items.Refresh();
38         }
39         // 跨线程调用控件
40         private void btn1_Click(object sender, RoutedEventArgs e)
41         {
42             Thread t1 = new Thread(() =>
43             {
44                 // 获取这些新添加的记录
45                 List<Information> lstInformati = new List<Information>();
46                 Information information = new Information();
47                 information.公司名称 = "公司名称跨线程";
48                 information.姓名 = "姓名跨线程";
49                 information.年龄 = "年龄跨线程";
50                 information.职务 = "职务跨线程";
51                 lstInformati.Add(information);
52                 Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
53                 {
54                     dgtext.ItemsSource = lstInformati;
55                     dgtext.Items.Refresh();
56                 });
57             })
58             {
59                 IsBackground = true
60             };
61             t1.Start();
62     }
63         // 跨类调用控件
64         private void btn2_Click(object sender, RoutedEventArgs e)
65         {
66             TreadTest1 treadTest1 = new TreadTest1();
67             treadTest1.TestC(this.dgtext);
68         }
69         // 跨线程跨类调用控件
70         private void btn3_Click(object sender, RoutedEventArgs e)
71         {
72             Thread t1 = new Thread(TestITC);
73             t1.Start();
74         }
75 
76         private void TestITC()
77         {
78             TreadTest1 treadTest1 = new TreadTest1();
79             treadTest1.TestITC( this.dgtext);
80         }
81     }
82 }

调用类代码:

 1 using System.Collections.Generic;
 2 using System.Windows.Threading;
 3 using System.Windows.Controls;
 4 using System.Threading;
 5 
 6 namespace WpfPaging.NewFolder1
 7 {
 8     //// 声明一个委托
 9     //public delegate void ChangeForm1TextBoxValue(string txt);
10     public class TreadTest1
11     {
12         //// 委托事件
13         //public event ChangeForm1TextBoxValue ChangeTextBoxValue;
14         /// <summary>
15         /// 跨类调用控件
16         /// </summary>
17         internal void TestC(System.Windows.Controls.DataGrid dgtext)
18         {
19             // 获取这些新添加的记录
20             List<Information> lstInformati = new List<Information>();
21             Information information = new Information();
22             information.公司名称 = "公司名称 跨类";
23             information.姓名 = "姓名 跨类";
24             information.年龄 = "年龄 跨类";
25             information.职务 = "职务 跨类";
26             lstInformati.Add(information);
27             dgtext.ItemsSource = lstInformati;
28             dgtext.Items.Refresh();
29         }
30         /// <summary>
31         /// 跨线程跨类调用控件
32         /// </summary>
33         /// <param name="dgtext"></param>
34         internal void TestITC(DataGrid dgtext)
35         {
36             // 获取这些新添加的记录
37             List<Information> lstInformati = new List<Information>();
38             Information information = new Information();
39             information.公司名称 = "跨线程跨类调用控件";
40             information.姓名 = "跨线程跨类调用控件";
41             information.年龄 = "跨线程跨类调用控件";
42             information.职务 = "跨线程跨类调用控件";
43             lstInformati.Add(information);
44             dgtext.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
45             {
46                 dgtext.ItemsSource = lstInformati;
47                 dgtext.Items.Refresh();
48             });
49         }
50     }
51 }
关于Dispatcher.Invoke的理解请见下面的链接
smallerpig的博客-Dispatcher.Invoke 方法
微软官方文档-Dispatcher 类
微软官方文档-Dispatcher.Invoke 方法
微软官方文档-Dispatcher.BeginInvoke 方法
线程与委托链接:
线程学习笔记
C#委托
Thread类接收ThreadStart委托或ParameterizedThreadStart委托的构造函数的模板
 
365个夜晚,我希望做到两天更一篇博客。加油,小白!
原文地址:https://www.cnblogs.com/qq2806933146xiaobai/p/14148371.html