WPF 之 线程使用
但凡涉及到图形界面,往往的设计都是不支持或者不推荐使用多个线程操作界面内容。而且通常会有一个专门的线程调度器来处理任务线程和界面线程的问题。
下面提供两个方案:
1、使用Dispatcher.BeginInvoke
这个方法简单暴力适合小工作量的修改一些界面内容。使用Dispatcher.BeginInvoke()会将代码安排为调度程序的一个任务。
步骤
- 使用Thread新建并开始一个线程
- 在新建的线程处理函数中需要修改界面的时候获取界面的dispatcher
- 使用Dispatcher的BeginInvoke方法指定一个线程优先级,和一个委托,这个委托时用于修改界面内容的
下面给出一部分代码
//新建线程
Thread thread = new Thread(UpdateTextRight);
thread.Start();
下面是新线程中的方法
//这个事例刚好是先窗体类中定义的,所以获取Dispatcher变得比较方便,而且使用了匿名委托.在通常的代码中会把委托给分离出去比较好.
private void UpdateTextRight()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart) delegate()
{
txt.Text = "Here is some new text.";
}
);
}
2、使用BackgroupWorker
这个类是专门用于简化Windows Form程序与线程相关的问题设计的,同样适用于WPF程序.适合于一个长期的后台进程,支持进度通知,取消支持,完成通知等功能。
使用方法也很简单,创建一个BackfruopWorker实例,它有几个事件.
DoWork事件会在另外一个线程中执行,用RunWorkerAsync()启动.所以在这个事件中不要去处理修改界面的事情
RunWorkerCompleted事件,在DoWork事件返回时(正常或者异常返回),在图形的线程中执行,所以可以修改界面
ProgressChanged事件,使用ReportProgress()方法调用,同时是在图形界面的线程中执行,通常负责修改一下进度条什么的.而ReportProgress()方法,通常会在DoWork的事件 中调用,然后给一个百分比的值.要使用这个功能,需要把WorkerReportsProgress属性设置成true
另外值得一说的是,要取消支持需要把WorkerSupportsCancellation属性设为true,使用CancelAsync()方法调用,但是这个调用不会终止进程,所以在DoWork事件中需要判断CancellationPending.
下面给出部分代码
创建BackgroundWorker实例
BackgroundWorker backgroundWorker;
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; //可以返回工作进度
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged; //允许取消
backgroundWorker.WorkerSupportsCancellation = true;
开始执行DoWork
backgroundWorker.RunWorkerAsync();
DoWork事件范例,这个方法的内容是在另外一个线程,异步执行得
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while(!backgroundWorker.CancellationPending)
{
//Do SomeThing
//在合适的时候使用
//backgroundWorker.ReportProgress(i);
//报告一下进度,其中i是0-100的整数
}
//这里可以使用e.Result给一个返回值,如果有需要的话
}
进度改变时的处理事件,也就是修改一下进度条什么的
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
完成事件我就不演示,下面是取消任务的方法
private void cmdCancel_Click(object sender, RoutedEventArgs e)
{
backgroundWorker.CancelAsync();
}
WPF 之 线程使用的更多相关文章
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
本文说明WPF [调用线程无法访问此对象,因为另一个线程拥有该对象.] 解决方案以及如何实现字体颜色的渐变 先来看看C#中Timer的简单说明,你想必猜到实现需要用到Timer的相关知识了吧. C# ...
- WPF不同线程之间的控件的访问
原文:WPF不同线程之间的控件的访问 WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public voi ...
- WPF的线程模型
原文:WPF的线程模型 WPF的线程模型 周银辉 谈到多线程,很多人对其可能都不太有好感,觉得麻烦与易出错.所以我们不排除有这样的情况:假设我对“多线程”.“异步”这些字眼潜意识 ...
- WPF跨线程操作UI界面控件
在WPF应用中,如果遇到多线程的需求时,如果引用WPF控件时会引发异常,异常内容:调用线程无法访问此对象,因为另一个线程拥有该对象.具体如下: 调用代码: ThreadcountThread= ...
- WPF 通过线程使用ProcessBar
WPF下使用进度条也是非常方便的,如果直接采用循环然后给ProcessBar赋值,理论上是没有问题的,不过这样会卡主主UI线程,我们看到的效果等全部都结束循环后才出现最后的值. 所以需要采用线程或者后 ...
- WPF后台线程更新UI
0.讲点废话 最近在做一个文件搜索的小软件,当文件多时,界面会出现假死的状况,于是乎想到另外开一个后台线程,更新界面上的ListView,但是却出现我下面的问题. 1.后台线程问题 2年前写过一个软件 ...
- WPF子线程更新UI(Dispatcher.BeginInvoke)
在做WPF开发时,如果直接在子线程里更新UI会报错—–“调用线程无法访问此对象,因为另一个线程拥有该对象.”,这是因为WPF禁止在非UI线程里直接更新UI界面. 解决方案: 在子线程里调用D ...
- wpf 调用线程必须为sta 因为许多ui组件都需要
解决 办法 public void SomeMethod() { var task = System.Windows.Application.Current.Dispatcher.BeginInvok ...
- wpf程序线程与UI内容交互
在UI线程里执行复杂的操作,会造成UI假死.常用的解决方法是开2个线程. 而新线程要调用UI里的东西,必须这么用: this.Dispatcher.Invoke(content);
随机推荐
- Instagram的技术探索2(转)
原文:http://www.cnblogs.com/xiekeli/archive/2012/05/28/2520770.html 前一篇翻译了Instagram blog上的一篇文章<What ...
- NSLog中的%@
[NSLog中的%@] There is one additional substitution token available in Objective-C, %@, used to denote ...
- USB的四种传输类型
USB协议规定了4种传输类型:批量(bulk)传输,等时传输(同步传输),中断传输和控制传输.
- Window服务初级教程以及log4net配置文件初始化
Window服务初级教程:http://www.jb51.net/article/48987.htm 另外,配置log4net这个日志功能的时候需要初始化,不然会报没有初始化的错误,而且初始化的节点应 ...
- CodeForces 702 A Maximum Increase (贪心,高效算法)
题意:给定 n 个数,问你连续的最长的序列是几个. 析:从头扫一遍即可. 代码如下: #include <cstdio> #include <string> #include ...
- php中定义类
<?php class Person{ //定义了一个Person类 public $name; //定义属性name public $age; //定义属性age function __con ...
- LDA(Latent Dirichlet Allocation)
转自:http://leyew.blog.51cto.com/5043877/860255#559183-tsina-1-46862-ed0973a0c870156ed15f06a6573c8bf0 ...
- [XAF]如何在非按钮事件中打开视图
private static void OpenDetailView(XafApplication app) { IObjectSpace os = app.CreateObjectSpace(); ...
- VC++ 中滑动条(slider控件)使用 [转+补充]
滑动控件slider是Windows中最常用的控件之一.一般而言它是由一个滑动条,一个滑块和可选的刻度组成,用户可以通过移动滑块在相应的控件中显示对应的值.通常,在滑动控件附近一定有标签控件或编辑框控 ...
- C#FTP下载文件出现远程服务器返回错误: (500) 语法错误,无法识别命令
如果下载多个文件的时候,有时候莫名其妙的出现500服务器错误,很有可能是没有设置KeepAlive 属性导致的. 出现应用程序未处理的异常:2015/1/6 11:40:56 异常类型:WebExce ...