标签:
=============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ========== 未经允许不许转载 =========
System.Windows.Threading.Dispatcher类(wpf新增的)
DispatcherObject类(Dispatcher,CheckAccess(),VerifyAccess())
具有线程关联性的WPF对象都在类层次的某个位置继承自DispatcherObject类。
demo1:普通线程方式
界面:
<Grid> <Button x:Name="btn1" Content="更新文本" HorizontalAlignment="Left" Margin="209,50,0,0" VerticalAlignment="Top" Width="75" Click="btn1_Click"/> <TextBox x:Name="tb1" HorizontalAlignment="Left" Height="23" Margin="26,50,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/> </Grid>
后台:
private void btn1_Click(object sender, RoutedEventArgs e) { Thread t = new Thread(updateTxt); t.Start(); } private void updateTxt() { Thread.Sleep(TimeSpan.FromSeconds(5)); tb1.Text = "你好阳光"; }
失败了
updateTxt()方法在新线程上运行,不允许访问WPF对象。TextBox对象调用VerifyAccess()方法捕获异常。(aaronyang博客)
使用WPF方式将操作封送到调度程序线程即可
private void updateTxt() { Thread.Sleep(TimeSpan.FromSeconds(5)); //tb1.Text = "你好阳光"; this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { tb1.Text = "你好阳光"; }); }
此时拖动窗口也没有卡顿。5秒后自动更新界面。第一个参数是优先级。DispatcherPriority.SystemIdle表示CPU空闲状态。DispatcherPriority.ApplicationIdle应用程序空闲时候再操作。
BeginInvoke返回线程信息,可控制,也可以获得执行状态,我在前台加了个进度条
private void updateTxt() { Thread.Sleep(TimeSpan.FromSeconds(5)); //tb1.Text = "你好阳光"; //this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (ThreadStart)delegate() //{ // tb1.Text = "你好阳光"; //}); //可用于判断是否完成 var dispatcherOperation = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { Thread.Sleep(TimeSpan.FromSeconds(5)); tb1.Text = "你好阳光"; }); while (!(dispatcherOperation.Status==DispatcherOperationStatus.Completed)) { } this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { pb1.Value = 100; }); }
Invoke是同步的方法,BeginInvoke是异步的。
System.ComponentModel.BackgroundWorker类
还提供了进度事件和取消消息,由于BackgroundWorker不可见,所以声明在窗口的资源里面,我们需要引入空间
<Window x:Class="multhread.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cm="clr-namespace:System.ComponentModel;assembly=System" Title="MainWindow" Height="350" Width="525">
DEMO2
<Window.Resources> <cm:BackgroundWorker x:Key="bw" WorkerReportsProgress="True" WorkerSupportsCancellation="True" DoWork="BackgroundWorker_DoWork" RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted" ProgressChanged="BackgroundWorker_ProgressChanged" ></cm:BackgroundWorker> </Window.Resources>
后台获得
private BackgroundWorker bw; public int sum = 0; public MainWindow() { InitializeComponent(); bw = (BackgroundWorker)this.FindResource("bw"); }
OK,接下来我们来做个后台耗时的操作,我们使用Thread模拟吧,前台定义好界面
<Window x:Class="multhread.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cm="clr-namespace:System.ComponentModel;assembly=System" Title="从1加到10 aaronyang demo" Height="350" Width="525"> <Window.Resources> <cm:BackgroundWorker x:Key="bw" WorkerReportsProgress="True" WorkerSupportsCancellation="True" DoWork="BackgroundWorker_DoWork" RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted" ProgressChanged="BackgroundWorker_ProgressChanged" ></cm:BackgroundWorker> </Window.Resources> <Grid> <Button x:Name="btn1" Content="开始增加" HorizontalAlignment="Left" Margin="21,70,0,0" VerticalAlignment="Top" Width="75" Click="btn1_Click" IsEnabled="true"/> <Button x:Name="btn2" Content="取消增加" HorizontalAlignment="Left" Margin="101,70,0,0" VerticalAlignment="Top" Width="75" Click="btn2_Click" IsEnabled="False"/> <TextBox x:Name="tb1" HorizontalAlignment="Left" Height="23" Margin="76,10,0,0" TextWrapping="Wrap" Text="10" VerticalAlignment="Top" Width="120"/> <ProgressBar x:Name="pb1" HorizontalAlignment="Left" Height="16" Margin="21,108,0,0" VerticalAlignment="Top" Width="289" Maximum="100" Minimum="0"/> <Label Content="目标分数" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/> <Label Content="当前分数:" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top"/> <Label x:Name="lblPoint" Content="0" HorizontalAlignment="Left" Margin="78,39,0,0" VerticalAlignment="Top" RenderTransformOrigin="0,-0.2"/> </Grid> </Window>
后台看代码没啥解释的。
/// <summary> /// 开始线程 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn1_Click(object sender, RoutedEventArgs e) { //Thread t = new Thread(updateTxt); //t.Start(); btn1.IsEnabled = false; btn2.IsEnabled = true; int grade=Convert.ToInt32(tb1.Text); bw.RunWorkerAsync(grade); }
然后开始了Dowork的方法
private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { int max = (int)e.Argument; long c = 0; for (int i = 1; i <= max; i++) { System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(200));//每完成1次相当于10% c = c + i; bw.ReportProgress(i * 10); } e.Result = c; }
dowork完以后,会返回最终结果,我们在Completed中显示结果
private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else { lblPoint.Content = e.Result.ToString(); } }
我们在dowork时候,调用ReportProgress报告进度
private void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) { pb1.Value = e.ProgressPercentage; }
取消线程
//取消线程 private void btn2_Click(object sender, RoutedEventArgs e) { bw.CancelAsync(); }
然后,在dowork中判断,是否取消,如果取消就结束。
private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { int max = (int)e.Argument; long c = 0; for (int i = 1; i <= max; i++) { if (bw.CancellationPending) { e.Cancel = true; return; } System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(500));//每完成1次相当于10% c = c + i; bw.ReportProgress(i * 10); } e.Result = c; } private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) { if (e.Cancelled) { //MessageBox.Show("操作已经取消"); pb1.Value = 0; btn1.IsEnabled = true; btn2.IsEnabled = false; return; } else { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else { lblPoint.Content = e.Result.ToString(); } btn1.IsEnabled = true; btn2.IsEnabled = false; } }
效果图:
这个简单的DEMO就先当这里了
=============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ========== 未经允许不许转载 =========
-------------------小小的推荐,作者的肯定,读者的支持。推不推荐不重要,重要的是希望大家能把WPF推广出去,别让这么好的技术消失了,求求了,让我们为WPF技术做一份贡献。------
[Aaronyang] 写给自己的WPF4.5 笔记16[多线程]
标签:
原文地址:http://www.cnblogs.com/AaronYang/p/4313202.html