C# Wpf异步修改UI,多线程修改UI(二)
1.使用定时器异步修改
这是相对比较简单的方法
在Wpf中定时器使用DiapatcherTimer,不使用Timer原因:
在一个应用程序中,Timer会重复生成time事件,而DispatcherTimer是一个集成到了Dispatcher队列中的时钟,这可以使它被按照指定的时间间隔以指定的priority定期执行。
对于一个Timer时钟事件,系统并不能保证在时间间隔到达后被立即执行,但是能够确保在时间间隔到达之前不被执行。这是因为DispatcherTimer像其他操作一样被放置在了Dispatcher队列中。何时执行DispatcherTimer事件依赖于队列中的其他任务以及他们的优先级.
如果一个WPF应用程序使用了Timer时钟,那么它的事件必须在一个单独的时钟线程中运行,而不是在UI线程中,这对于WPF应用程序毫无用处——你没法在UI线程之外直接访问UI元素,而只能通过Invoke或者BeginInvoke将操作发送给Dispatcher 对象,委托Dispatcher去执行UI操作。
看到这里,你大概知道了为什么我们在WPF中应该用DispatcherTimer而不是Timer了:DispatcherTimer与Dispatcher运行于同一个线程中——UI线程,而且具有相同的DispatcherPriority优先级。
实例:
Xaml代码:
<Grid>
<TextBox x:Name="textBox" Padding="10"
Height="45"
TextWrapping="Wrap" Text="TextBox"
VerticalAlignment="Top" Margin="10,105,10,0"/>
</Grid>
后台代码:
//启动其他线程处理,调用失败
//Task.Run(()=> {
// DispatcherTimerHelper.DoWork(textBox);
//}); //主线程调用成功
DispatcherTimerHelper.DoWork(textBox);
public class DispatcherTimerHelper
{
//定时器,在指定事件内重复执行
//在非主线程中,会出现异常,当前线程结束
static DispatcherTimer _timer = new DispatcherTimer();
public static void DoWork(TextBox textBlock)
{
_timer.Interval = new TimeSpan(, , );
EventHandler event1 = new EventHandler(timer_Tick);
_timer.Tick += event1;
_timer.Tag = textBlock;
_timer.Start();
}
public static void Stop()
{
_timer.Stop();
}
static void timer_Tick(object sender, EventArgs e)
{
DispatcherTimer timer = sender as DispatcherTimer;
TextBox box = timer.Tag as TextBox;
box.Text = "张三"+DateTime.Now;
}
}

2.使用BackgroundWorker
这个类是专门用于简化Windows Form程序与线程相关的问题设计的,同样适用于WPF程序.适合于一个长期的后台进程,支持进度通知,取消支持,完成通知等功能.
使用方法也很简单,创建一个BackfruopWorker实例,它有几个事件.
DoWork事件会在另外一个线程中执行,用RunWorkerAsync()启动.所以在这个事件中不要去处理修改界面的事情
RunWorkerCompleted事件,在DoWork事件返回时(正常或者异常返回),在图形的线程中执行,所以可以修改界面
ProgressChanged事件,使用ReportProgress()方法调用,同时是在图形界面的线程中执行,通常负责修改一下进度条什么的.而ReportProgress()方法,通常会在DoWork的事件中调用,然后给一个百分比的值.要使用这个功能,需要把WorkerReportsProgress属性设置成true
另外值得一说的是,要取消支持需要把WorkerSupportsCancellation属性设为true,使用CancelAsync()方法调用,但是这个调用不会终止进程,所以在DoWork事件中需要判断CancellationPending.
实例:
Xaml代码:
<StackPanel>
<ProgressBar Name="progressBar" Height="20" Width="200" Margin="10,80,20,10"></ProgressBar>
<Button Name="btnProcess" Width="100" Click="btnProcess_Click" Margin="5">开始后台任务</Button>
<Button Name="btnCancel" Width="100" Click="btnCancel_Click" Margin="5">取消后台任务</Button>
<Label x:Name="label" Content="Label" Margin="10"/>
</StackPanel>
C#后台代码:
/// <summary>
/// Thread9.xaml 的交互逻辑
/// </summary>
public partial class Thread9 : Window
{
BackgroundWorker bgWorker = new BackgroundWorker();
public Thread9()
{
InitializeComponent(); bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
//执行任务代码
bgWorker.DoWork += DoWork_Handler;
//执行过程触发
bgWorker.ProgressChanged += ProgressChanged_Handler;
//执行结束,或有异常结束触发
bgWorker.RunWorkerCompleted += RunWorkerCompleted_Handler;
}
private void btnProcess_Click(object sender, RoutedEventArgs e)
{
//开始执行
if (!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync();
}
}
private void ProgressChanged_Handler(object sender, ProgressChangedEventArgs args)
{
//在过程改变事件中可以修改UI内容
progressBar.Value = args.ProgressPercentage;
label.Content = "ProgressChanged方法执行完成" + args.ProgressPercentage;
}
private void DoWork_Handler(object sender, DoWorkEventArgs args)
{
//在DoWork中修改UI同样会抛出异常
//label.Content = "DoWork方法执行完成";
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = ; i <= ; i++)
{
if (worker.CancellationPending)
{
args.Cancel = true;
break;
}
else
{
//手动触发触发过程,代码执行
worker.ReportProgress(i);
Thread.Sleep();
}
}
}
private void RunWorkerCompleted_Handler(object sender, RunWorkerCompletedEventArgs args)
{
progressBar.Value = ;
if (args.Cancelled)
{
MessageBox.Show("后台任务已经被取消。", "消息");
}
else
{
MessageBox.Show("后台任务正常结束。", "消息");
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
//结束执行
bgWorker.CancelAsync();
}
}

C# Wpf异步修改UI,多线程修改UI(二)的更多相关文章
- 【转】WPF 异步执行方法后对 UI 进行更新的几种方法
使用 async/await 的情况: private async void Button_Click(object sender, RoutedEventArgs e) { (sender as B ...
- WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )
WPF:谈谈各种多线程去修改或访问UI线程数据的方法http://www.cnblogs.com/mgen/archive/2012/03/10/2389509.html 子线程非法访问UI线程的数据 ...
- 拒绝卡顿——在WPF中使用多线程更新UI
原文:拒绝卡顿--在WPF中使用多线程更新UI 有经验的程序员们都知道:不能在UI线程上进行耗时操作,那样会造成界面卡顿,如下就是一个简单的示例: public partial class MainW ...
- WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)
原文 WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口) WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验.如果希望做不同线程 ...
- C# Windows Phone App 开发,自制LockScreen 锁定画面类别(Class),从【网路图片】、【Assets资源】、【UI】修改锁定画面。
原文:C# Windows Phone App 开发,自制LockScreen 锁定画面类别(Class),从[网路图片].[Assets资源].[UI]修改锁定画面. 一般我们在开发Windows ...
- WPF里面多线程访问UI线程、主线程的控件
如果出现以下错误:调用线程无法访问此对象,因为另一个线程拥有该对象. 你就碰到多线程访问UI线程.主线程的控件的问题了. 先占位.
- Android UI 统一修改Button控件的样式,以及其它系统控件的默认样式
先介绍下修改原理:首先打开位于android.widget包下面的Button.java文件,这里有一句关键的代码如下: public Button(Context context, Attribut ...
- WPF 非UI线程更新UI界面的各种方法小结
转载:https://www.cnblogs.com/bdbw2012/articles/3777594.html 我们知道只有UI线程才能更新UI界面,其他线程访问UI控件被认为是非法的.但是我们在 ...
- Tkinter 吐槽之一:多线程与 UI 交互
背景 最近想简单粗暴的用 Python 写一个 GUI 的小程序.因为 Tkinter 是 Python 自带的 GUI 解决方案,为了部署方便,就直接选择了 Tkinter. 本来觉得 GUI 发展 ...
- (四)开源C# WPF控件库《AduSkin – UI》
微信公众号:[Dotnet9的博客],网站:[Dotnet9],问题或建议:[请网站留言], 如果对您有所帮助:[欢迎赞赏]. 开源C# WPF控件库系列: (一)开源C# WPF控件库<Mat ...
随机推荐
- Yeoman:适合现代Web应用的现代工作流
Yeoman:适合现代Web应用的现代工作流 Yeoman是Google的团队和外部贡献者团队合作开发的,他的目标是通过Grunt(一个用于开发任务自动化的命令行工具)和Bower(一个HTML. ...
- JVM中内存回收深入分析,各种垃圾收集器
JVM启动有两种模式,client和server 一般JVM启动时会根据主机情况分析选择采用那种模式启动 可发现是server模式 JVM中尤其需要关注的就是HEAP堆区 堆区分为新生代和老年代 新生 ...
- 设置Git提交时不用输入用户名和密码
在用git提交时代码至github上时每次都要输入用户名和密码,当提交操作较为频繁时非常不方便,可以按下文中的介绍,设置成提交时不用输入用户名和密码: 1.在当前库下,已经运行过 git remote ...
- 图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 344 Solved: 181[Submit][Stat ...
- workflow4.0学习资料
http://www.cnblogs.com/foundation/archive/2010/04/03/1703809.html 2篇说明: WF4 Bata 2 WF4.0 RC 对比 Beta2 ...
- 第一个ios程序
1.ios的理解: Operating System,简称OS,操作系统,ios是苹果操作系统. 2.Xcode开发环境: 苹果公司开发的编程软件,是开发人员建立OS X 和 iOS 应用程序的最快捷 ...
- 微信支付【get_brand_wcpay_request:fail_invalid appid】
微信支付授权目录一定要注意大小写 艹 如下的WXPay2 千万不要写成WxPay2了 参考地址:http://q.cnblogs.com/q/70405/ 微信支付代码下载:http://files. ...
- android webview load 本地文件需要注意的地方
记得在工程的main下必须是assets文件夹. 而webview.loadUrl时 必须是 android_asset 必须这样对应,否则无法加载本地html. 具体原因只能在深入学习后再总结了 ...
- H - Pots
题目大意: 有一个瓶子A和一个瓶子B,可以有三种操作倒满,倒空,或者把瓶子A倒向瓶子B(或者把瓶子B倒向瓶子A),可以扩展出6种操作,没什么简单的写法,只能一种一种的写..... 当然是使用广搜... ...
- 在Eclipse工具里创建maven的web工程,在建立src/main/java包出现The folder is already a source folder.解决
1. 与创建普通java工程一样,点击右键找到New菜单,在弹出的界面输入maven ---->>点击maven Project------>>点击next 2 进入下一个界 ...