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,如需转载请自行联系原作者

相关文章
|
21天前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
50 12
|
5月前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
78 3
|
3月前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
150 29
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
2月前
|
存储 运维 API
源码解密协程队列和线程队列的实现原理(一)
源码解密协程队列和线程队列的实现原理(一)
41 1
|
2月前
|
存储 安全 API
源码解密协程队列和线程队列的实现原理(二)
源码解密协程队列和线程队列的实现原理(二)
37 1
|
2月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
81 0
|
3月前
|
监控 Java
线程池中线程异常后:销毁还是复用?技术深度剖析
在并发编程中,线程池作为一种高效利用系统资源的工具,被广泛用于处理大量并发任务。然而,当线程池中的线程在执行任务时遇到异常,如何妥善处理这些异常线程成为了一个值得深入探讨的话题。本文将围绕“线程池中线程异常后:销毁还是复用?”这一主题,分享一些实践经验和理论思考。
160 3
|
4月前
|
API Windows
揭秘网络通信的魔法:Win32多线程技术如何让服务器化身超级英雄,同时与成千上万客户端对话!
【8月更文挑战第16天】在网络编程中,客户/服务器模型让客户端向服务器发送请求并接收响应。Win32 API支持在Windows上构建此类应用。首先要初始化网络环境并通过`socket`函数创建套接字。服务器需绑定地址和端口,使用`bind`和`listen`函数准备接收连接。对每个客户端调用`accept`函数并在新线程中处理。客户端则通过`connect`建立连接,双方可通过`send`和`recv`交换数据。多线程提升服务器处理能力,确保高效响应。
59 6
|
4月前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
4月前
三个线程交替打印ABC:技术深度解析与实战应用
【8月更文挑战第14天】在并发编程中,实现多个线程之间的精确协同工作是一项既具挑战性又极具实用价值的任务。今天,我们将深入探讨一个经典问题:如何使用三个线程交替打印字符A、B、C,且每个字符连续打印三次,之后循环进行。这个问题不仅考验了我们对线程同步机制的理解,还锻炼了我们在复杂并发场景下的设计能力。
83 0