Silverlight实用窍门系列:24.Silverlight多线程技术BackgroundWorker的应用,更新ProgressBar控件【附带源码实例】

简介:

 在Silverlight中极其耗时的操作会导致UI进程假死,如果将复杂的操作和UI显示分离开而且我们需要了解这复杂操作的后台进程当前运行的进度如何?这里我们可以使用BackgroundWorker来解决这个问题。

        BackgroundWorker是一个封装了的Thread组件,它能够让用户方便的开启一个独立的线程执行复杂和耗时的后台工作,随时报告当前完成程度,随时中止异步线程操作,还可以在异步操作状态报告中(ProgressChanged)和异步操作完成后(RunWorkerCompleted)的响应事件中访问UI线程。

        BackgroundWorker的一些常用的属性、方法和事件如下:

         •属性

             CancellationPending  获取一个值,指示应用程序是否已请求取消后台操作。 
             IsBusy  获取一个值,指示 BackgroundWorker 是否正在运行异步操作。 
             WorkerReportsProgress  获取或设置一个值,该值指示 BackgroundWorker 能否支持报告进度更新。 
             WorkerSupportsCancellation  获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。

         •方法

             CancelAsync  请求取消挂起的后台操作。  
             ReportProgress   引发 ProgressChanged 事件。  
             RunWorkerAsync  开始执行后台操作。
  
          •事件

             DoWork  调用 RunWorkerAsync 时发生。 
             ProgressChanged  调用 ReportProgress 时发生。 
             RunWorkerCompleted  当后台操作已完成、被取消或引发异常时发生。

        现在我们清理一下这个组件的运行思路:

        一、首先我们创建一个BackgroundWorker对象实例,然后设置它的属性WorkerReportsProgress、WorkerSupportsCancellation为ture,为BackgroundWorker实例的DoWork 、ProgressChanged 、RunWorkerCompleted 三个事件加载相应的事件处理方法。

        二、此时按下“运行按钮”,根据BackgroundWorker的IsBusy属性判断当前对象是否已经正在开始执行后台异步线程,如果未执行异步线程,则调用RunWorkerAsync()方法开始执行异步线程并且可以传递参数A,此时将触发DoWork事件,在这个事件内部是不能直接操作UI线程的。此时在DoWork响应时间内部首先判断CancellationPending属性是否为ture,如果为true表示当前已经取消异步进程运行,否则继续运行需要处理的复杂运算,可以通过e.Argument属性接收到参数A。

        三、在运行复杂运算的过程中,每隔一个时间段执行一次ReportProgress(int percentProgress)函数,传递当前运行完成百分数,此时为参数B,然后触发ProgressChanged事件,在此事件中通过e.ProgressPercentage属性接收到参数B,更新UI的ProgressBar控件,显示当前的完成进度。

        四、当DoWork内的复杂运算完毕之后为当前DoWork事件的e.Result赋值C,再触发RunWorkerCompleted 事件,此时在RunWorkerCompleted 事件中接受e.Result的值。将结果显示到UI界面上即可。

        下面我们来看一段实例程序源码MainPage.xaml.cs,相关的运行注释在代码中已经注明:

复制代码

  
  
public partial class MainPage : UserControl
{
// 声明一个BackgroundWorker对象实例
private BackgroundWorker bgWorker = new BackgroundWorker();
public MainPage()
{
InitializeComponent();
InitBackGroundWorker();
}
// 初始化BackgroundWorker的相关属性和加载事件
public void InitBackGroundWorker()
{
// BackgroundWorker是否支持报告执行进度
bgWorker.WorkerReportsProgress = true ;
// BackgroundWorker是否支持取消运行异步操作
bgWorker.WorkerSupportsCancellation = true ;
// 加载DoWork、ProgressChanged、RunWorkerCompleted事件
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged
+= new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted
+= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
}
// 后台异步执行操作的地方
void bgWorker_DoWork( object sender, DoWorkEventArgs e)
{
// 获取到传递进来的参数
string str = e.Argument.ToString();
// 执行100次循环
for ( int i = 0 ; i < 100 ; i ++ )
{
// 判断当前BackgroundWorker是否已经被取消了异步操作
if (bgWorker.CancellationPending == false )
{
// 如果没有被取消异步操作,则线程阻塞以下,然后报告给bgWorker_ProgressChanged事件
Thread.Sleep( 50 );
bgWorker.ReportProgress(i
+ 1 );
e.Result
= " 3322 " ;
}
else
{
// 设置当前已取消异步线程操作
e.Cancel = true ;
break ;
}
}
}
// 进度改变时触发的事件执行函数,这里显示执行进度
void bgWorker_ProgressChanged( object sender, ProgressChangedEventArgs e)
{
// 设置当前进度条的值为事件执行完成程度值
this .progressBar1.Value = e.ProgressPercentage;
}
// 异步操作执行完毕之后的处理
void bgWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e)
{

// 完成异步操作之后检查是否取消了异步操作,弹出相关提示
if (e.Cancelled == true )
{
MessageBox.Show(
" 取消异步线程操作 " );
}
else
{
MessageBox.Show(
" 异步线程执行完毕 " + e.Result);
}

this .btncancel.Content = " 已完成 " ;
}

private void btnrun_Click( object sender, RoutedEventArgs e)
{
// 如果后台进程未开始运行,则开始运行线程
if (bgWorker.IsBusy != true )
{
bgWorker.RunWorkerAsync(
" 我是参数 " );
}
}

private void btncancel_Click( object sender, RoutedEventArgs e)
{
// 取消异步操作。
bgWorker.CancelAsync();
}
}
复制代码

        本实例采用VS2010+Silverlight 4.0编写,点击 SLBackgroundWorker_Caleung.rar 下载本实例源码。



    本文转自程兴亮博客园博客,原文链接:http://www.cnblogs.com/chengxingliang/archive/2011/03/11/1981623.html,如需转载请自行联系原作者

相关文章
|
9月前
|
安全 Java 调度
Netty源码—3.Reactor线程模型二
本文主要介绍了NioEventLoop的执行总体框架、Reactor线程执行一次事件轮询、Reactor线程处理产生IO事件的Channel、Reactor线程处理任务队列之添加任务、Reactor线程处理任务队列之执行任务、NioEventLoop总结。
|
9月前
|
安全 Java
Netty源码—2.Reactor线程模型一
本文主要介绍了关于NioEventLoop的问题整理、理解Reactor线程模型主要分三部分、NioEventLoop的创建和NioEventLoop的启动。
|
10月前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
379 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
|
10月前
|
Java
线程池是什么?线程池在实际工作中的应用
总的来说,线程池是一种有效的多线程处理方式,它可以提高系统的性能和稳定性。在实际工作中,我们需要根据任务的特性和系统的硬件能力来合理设置线程池的大小,以达到最佳的效果。
291 18
|
11月前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
540 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
288 12
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
887 6
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
305 8
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
监控 Java 数据库连接
Java线程管理:守护线程与用户线程的区分与应用
在Java多线程编程中,线程可以分为守护线程(Daemon Thread)和用户线程(User Thread)。这两种线程在行为和用途上有着明显的区别,了解它们的差异对于编写高效、稳定的并发程序至关重要。
359 2

热门文章

最新文章