SilverLight学习笔记--Silverligh之BackgroundWorker类的应用

本文介绍如何在Silverlight应用中使用BackgroundWorker类执行后台任务,包括如何设置属性、绑定事件处理程序及调用方法等。并通过一个示例程序详细展示了从1累加到6的过程中如何更新UI和处理取消请求。
摘要由CSDN通过智能技术生成

   在Silverlight应用中,我们可能会遇到一些操作(如:下载某个资源或某些数据库事务或完成某些特定动作),这些操作耗时较长,容易造成“用户界面停止响应”的现象。如果您需要能进行响应的用户界面,而且必须执行耗时操作,则可以使用 BackgroundWorker 类方便地解决问题。 BackgroundWorker 类是.net 2.0里新增的一个类。 使用 BackgroundWorker 类,我们可以在 Silverlight 用户界面中指示操作进度、完成和取消情况。例如,可以查看后台操作是已完成还是已取消并为用户显示消息。
    一、BackgroundWorker类的基本了解
       涉及的命名空间

   using  System.ComponentModel;

        它的几个属性:

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

        它的主要事件:

  DoWork——调用 RunWorkerAsync 时发生。 注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。 
  ProgressChanged——调用 ReportProgress 时发生。 
  RunWorkerCompleted——当后台操作已完成、被取消或引发异常时发生。

        它的有关方法:

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

  
   二、示例
    下面,我们就使用这个类来完成一个特定操作:
    用于执行从1累加到6.在累加过程中,SUM值会不断更新,当累加到6后,BackgroundWorker会在成功执行结束后调用一段程序来输出最终的运行信息。
    新建一个名为:SLBackgroundWorker的Silverlight应用程序,如图:
                        
   1、创建用户界面:
     Page.xaml代码如下:

< UserControl x:Class = " SLBackgroundWorker.Page "
    xmlns
= " http://schemas.microsoft.com/winfx/2006/xaml/presentation "  
    xmlns:x
= " http://schemas.microsoft.com/winfx/2006/xaml "  
    Width
= " 400 "  Height = " 350 " >
    
< Grid x:Name = " LayoutRoot "  Background = " White " >
        
< StackPanel Orientation = " Vertical "  Width = " 400 "  Height = " 350 "  Background = " Yellow "   >
            
< TextBlock x:Name = " txtDisplay "  FontSize = " 24 "  TextAlignment = " Center "  Margin = " 10 "  Text = " 当前无内容 "  Height = " 100 "   />
            
< Button x:Name = " btnRun "   Content = " 从1到6累加 "  Click = " OnRun "  Margin = " 10 "  Height = " 50 " />
            
< Button x:Name = " btnCancel "  Content = " 取 消 "  Click = " OnCancel "  Margin = " 10 "  Height = " 50 " />
            
< TextBlock x:Name = " txtUserState "  FontSize = " 12 "  TextAlignment = " Center "  Text = " 显示ReportProgress方法传回的userState值     " />
            
< TextBlock x:Name = " txtEdoArgs "  FontSize = " 12 "  TextAlignment = " Center "  Text = " 显示RunWorkerAsync()方法调用时传入的参数 " />
        
</ StackPanel >

    
</ Grid >
</ UserControl >

效果如下图
                        

2、使用BackgroundWorker类
     在此我们分四个步骤来操作
     2.1、声明一个BackgroundWorker类实例:若要在后台运行操作,请创建一个 BackgroundWorker。可以侦听报告操作进度并在操作完成时发出信号的事件。

 worker  = new  System.ComponentModel.BackgroundWorker();

 
     2.2、相关事件的定义
     若要设置后台操作,请为 DoWork 事件添加事件处理程序,在此事件处理程序中调用耗时的操作。

 

ContractedBlock.gif ExpandedBlockStart.gif Code
        #region 当前BackgroundWorker所执行操作
        
private void OnDoWork(object sender,DoWorkEventArgs e)
        {


              
//DoWorkEventArgs.Argument - RunWorkerAsync(object argument)传递过来的参数
              
//DoWorkEventArgs.Cancel - 取消操作
              
//DoWorkEventArgs.Result - 操作的结果。将传递到 RunWorkerCompleted 所指定的方法
              
//BackgroundWorker.ReportProgress(int percentProgress, object userState) - 向 ProgressChanged 汇报操作的完成进度
              
//   int percentProgress - 操作完成的百分比 1% - 100%
              
//    object userState - 传递到 ProgressChanged 的参数
   

            
//获取在 worker.RunWorkerAsync()方法中传来的参数
            
//在此处,我们把它赋值给了一个全局变量,并在OnProgressChanged过程中显示出来
            eStrAll = e.Argument.ToString();

            
int Value = 0;
            
//如果Value还没有加到6,并且应用程序还没有请求取消后台操作,则继续本循环
            while (Value <= 6 && !worker.CancellationPending)
            { 
                Thread.Sleep(
1000); //挂起1秒钟
                Value++;

                
#region 调用方法一:不传递UserState值
                worker.ReportProgress(Value);
                
#endregion

                
#region 调用方法一:要传递UserState值
                
// worker.ReportProgress(Value, "传来的UserState值  " + Value.ToString()); //此处还可以传递userState(状态对象)到RunWorkerAsync,并在OnProgressChanged中获取
                #endregion
            }

            
//如果应用程序请求取消后台操作,则取消
            if (worker.CancellationPending)
            {
                e.Cancel 
= true;
            }

            
#region 可以在此处设置e.Result的值,并在OnWorkCompleted事件中获取它的值
            e.Result 
= "操作已完成";
            
#endregion

        }
        
#endregion

       
      若要收到进度更新的通知,请处理 ProgressChanged 事件。
 

ContractedBlock.gif ExpandedBlockStart.gif Code
        #region  异步操作进度事件
        
private void OnProgressChanged(object sender, ProgressChangedEventArgs  e)
        {
            
// ProgressChangedEventArgs.ProgressPercentage - ReportProgress 传递过来的操作完成的百分比
            
// ProgressChangedEventArgs.UserState - ReportProgress 传递过来的参数

            txtDisplay.Text 
= e.ProgressPercentage.ToString(); //显示当前进度

            
#region 如果在OnDoWork中使用的是调用方法二,则在此可获取e.UserState值
            
//在此处获取从OnDoWork中的 worker.ReportProgress方法传回的userState值            
            
//txtUserState.Text = e.UserState.ToString();
            #endregion

            
#region 显示RunWorkerAsync()方法调用时传入的参数
            
this.txtEdoArgs.Text = eStrAll;
            
#endregion
        }
        
#endregion

      若要在操作完成时收到通知,请处理 RunWorkerCompleted 事件。
   

ContractedBlock.gif ExpandedBlockStart.gif Code
        #region 操作成功完成时的处理事件
        
private void OnWorkCompleted(object sender,   RunWorkerCompletedEventArgs e)
        {

              
//RunWorkerCompletedEventArgs.Error - DoWork 时产生的错误
              
//RunWorkerCompletedEventArgs.Cancelled - 后台操作是否已被取消
            
//RunWorkerCompletedEventArgs.Result - DoWork 的结果

            
#region  进行完成时的相关判断与处理
            
if (e.Error !=null)
            {
                txtDisplay.Text 
= "调用失败";
            }
            
else
            {
                
if(e.Cancelled)
                {
                    txtDisplay.Text 
= "已经取消本次操作!";
                }
                
else
                {
                    txtDisplay.Text 
= e.Result.ToString();// 可以在此处获取e.Result的值(它的值在OnDoWork中进行了设置)
                }

            }
            
#endregion
        }
        
#endregion


    若要 取消异步操作,则使用CancelAsync方法。

 

         #region  取消异步操作
        
private   void  OnCancel( object  sender, RoutedEventArgs e)
        {
            
// 取消异步操作 
            worker.CancelAsync();
        }
        
#endregion

     2.3、相关事件的绑定和操作设置

             #region  步骤二:相关事件的定义、绑定和操作设置
            
// 当前BackgroundWorker所执行的操作
            worker.DoWork  +=  OnDoWork;

            
// 绑定异步操作进度的事件
            worker.ProgressChanged  +=  OnProgressChanged;

            
// 绑定操作成功完成的处理事件
            worker.RunWorkerCompleted  +=  OnWorkCompleted;

            
// 是否报告进度更新
            worker.WorkerReportsProgress  =    true ;

            
// 是否支持异步取消
            worker.WorkerSupportsCancellation  =   true ;

            
#endregion

  2.4、开始执行后台操作
  若要启动后台操作,请调用 RunWorkerAsync 方法。

   #region  步骤三:开始执行后台操作
            
//  IsBusy - 指定的 BackgroundWorker 是否正在后台操作
            
//  RunWorkerAsync(object argument) - 开始在后台线程执行指定的操作
            
//      object argument - 需要传递到 DoWork 的参数
             if  ( ! worker.IsBusy)
                worker.RunWorkerAsync(
" 方法RunWorkerAsync调用时传递的参数 " );
            
#endregion


Page.xaml.cs全部代码如下:

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Net;
using  System.Windows;
using  System.Windows.Controls;
using  System.Windows.Documents;
using  System.Windows.Input;
using  System.Windows.Media;
using  System.Windows.Media.Animation;
using  System.Windows.Shapes;
using  System.ComponentModel; // 必须要引入此命名空间才能使用BackgroundWorker类
using  System.Threading;  // 必须要引入此命名空间才能执行 Sleep(1000)挂起1秒钟操作

namespace  SLBackgroundWorker
ExpandedBlockStart.gifContractedBlock.gif
{
    
public partial class Page : UserControl
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{

        
private  BackgroundWorker worker;
        
string eStrAll = "";  //用于保存调用RunWorkerAsync()方法时的传参,此传参在OnDoWork()方法中截取到

        
public Page()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            InitializeComponent();
        }


        
private void OnRun(object sender, RoutedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ContractedSubBlock.gifExpandedSubBlockStart.gif            
步骤一:声明一个BackgroundWorker类实例#region 步骤一:声明一个BackgroundWorker类实例
            worker 
=new System.ComponentModel.BackgroundWorker();
            
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif            
步骤二:相关事件的定义、绑定和操作设置#region 步骤二:相关事件的定义、绑定和操作设置
            
//当前BackgroundWorker所执行的操作
            worker.DoWork += OnDoWork;

            
//绑定异步操作进度的事件
            worker.ProgressChanged += OnProgressChanged;

            
//绑定操作成功完成的处理事件
            worker.RunWorkerCompleted += OnWorkCompleted;

            
//是否报告进度更新
            worker.WorkerReportsProgress =  true;

            
//是否支持异步取消
            worker.WorkerSupportsCancellation = true;

            
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif            
步骤三:开始执行后台操作#region 步骤三:开始执行后台操作
            
// IsBusy - 指定的 BackgroundWorker 是否正在后台操作
            
// RunWorkerAsync(object argument) - 开始在后台线程执行指定的操作
            
//     object argument - 需要传递到 DoWork 的参数
            if (!worker.IsBusy)
                worker.RunWorkerAsync(
"方法RunWorkerAsync调用时传递的参数");
            
#endregion


        }



ContractedSubBlock.gifExpandedSubBlockStart.gif        
当前BackgroundWorker所执行操作#region 当前BackgroundWorker所执行操作
        
private void OnDoWork(object sender,DoWorkEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{


              
//DoWorkEventArgs.Argument - RunWorkerAsync(object argument)传递过来的参数
              
//DoWorkEventArgs.Cancel - 取消操作
              
//DoWorkEventArgs.Result - 操作的结果。将传递到 RunWorkerCompleted 所指定的方法
              
//BackgroundWorker.ReportProgress(int percentProgress, object userState) - 向 ProgressChanged 汇报操作的完成进度
              
//   int percentProgress - 操作完成的百分比 1% - 100%
              
//    object userState - 传递到 ProgressChanged 的参数
   

            
//获取在 worker.RunWorkerAsync()方法中传来的参数
            
//在此处,我们把它赋值给了一个全局变量,并在OnProgressChanged过程中显示出来
            eStrAll = e.Argument.ToString();

            
int Value = 0;
            
//如果Value还没有加到6,并且应用程序还没有请求取消后台操作,则继续本循环
            while (Value <= 6 && !worker.CancellationPending)
ExpandedSubBlockStart.gifContractedSubBlock.gif            

                Thread.Sleep(
1000); //挂起1秒钟
                Value++;

ContractedSubBlock.gifExpandedSubBlockStart.gif                
调用方法一:不传递UserState值#region 调用方法一:不传递UserState值
                worker.ReportProgress(Value);
                
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif                
调用方法一:要传递UserState值#region 调用方法一:要传递UserState值
                
// worker.ReportProgress(Value, "传来的UserState值  " + Value.ToString()); //此处还可以传递userState(状态对象)到RunWorkerAsync,并在OnProgressChanged中获取
                #endregion

            }


            
//如果应用程序请求取消后台操作,则取消
            if (worker.CancellationPending)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                e.Cancel 
= true;
            }


ContractedSubBlock.gifExpandedSubBlockStart.gif            
可以在此处设置e.Result的值,并在OnWorkCompleted事件中获取它的值#region 可以在此处设置e.Result的值,并在OnWorkCompleted事件中获取它的值
            e.Result 
= "操作已完成";
            
#endregion


        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
异步操作进度事件#region  异步操作进度事件
        
private void OnProgressChanged(object sender, ProgressChangedEventArgs  e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
// ProgressChangedEventArgs.ProgressPercentage - ReportProgress 传递过来的操作完成的百分比
            
// ProgressChangedEventArgs.UserState - ReportProgress 传递过来的参数

            txtDisplay.Text 
= e.ProgressPercentage.ToString(); //显示当前进度

ContractedSubBlock.gifExpandedSubBlockStart.gif            
如果在OnDoWork中使用的是调用方法二,则在此可获取e.UserState值#region 如果在OnDoWork中使用的是调用方法二,则在此可获取e.UserState值
            
//在此处获取从OnDoWork中的 worker.ReportProgress方法传回的userState值            
            
//txtUserState.Text = e.UserState.ToString();
            #endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif            
显示RunWorkerAsync()方法调用时传入的参数#region 显示RunWorkerAsync()方法调用时传入的参数
            
this.txtEdoArgs.Text = eStrAll;
            
#endregion

        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
操作成功完成时的处理事件#region 操作成功完成时的处理事件
        
private void OnWorkCompleted(object sender,   RunWorkerCompletedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

              
//RunWorkerCompletedEventArgs.Error - DoWork 时产生的错误
              
//RunWorkerCompletedEventArgs.Cancelled - 后台操作是否已被取消
            
//RunWorkerCompletedEventArgs.Result - DoWork 的结果

ContractedSubBlock.gifExpandedSubBlockStart.gif            
进行完成时的相关判断与处理#region  进行完成时的相关判断与处理
            
if (e.Error !=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                txtDisplay.Text 
= "调用失败";
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if(e.Cancelled)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    txtDisplay.Text 
= "已经取消本次操作!";
                }

                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    txtDisplay.Text 
= e.Result.ToString();// 可以在此处获取e.Result的值(它的值在OnDoWork中进行了设置)
                }


            }

            
#endregion

        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
取消异步操作#region 取消异步操作
        
private void OnCancel(object sender, RoutedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//取消异步操作 
            worker.CancelAsync();
        }

        
#endregion

    }

}

运行效果如下:

 

说明:
 1、您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
 2、如果后台操作需要参数,请在调用 RunWorkerAsync 时给出参数。在 DoWork 事件处理程序内部,可以从DoWorkEventArgs提取该参数。


前往:Silverlight学习笔记清单


本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值