C# 如何取消BackgroundWorker异步操作

BackgroundWorker 在执行DoWork事件时该如何取消呢?

 

方法1 DoWork 执行一个(耗时)循环

 

方法2 DoWork执行一个(耗时)方法[注:方法没有循环]

 

见代码:

方法1中DoWork事件执行的是一个for循环(foreach,while.....) 

 

取消操作很简单,只要在循环中判断即可

 

看代码---------代码是从网上拷贝下来的,这种例子网上很多

 

  1. #region  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Text;  
  6. using System.ComponentModel;  
  7. using System.Threading;  
  8. using System.Text.RegularExpressions;  
  9.   
  10. namespace ConsoleBackgroundworker  
  11. {  
  12.   class Program  
  13.   {  
  14.     static BackgroundWorker bw;  
  15.     static void Main()  
  16.     {  
  17.       bw = new BackgroundWorker();  
  18.       bw.WorkerReportsProgress = true;  
  19.       bw.WorkerSupportsCancellation = true;  
  20.       bw.DoWork += bw_DoWork;  
  21.       bw.ProgressChanged += bw_ProgressChanged;  
  22.       bw.RunWorkerCompleted += bw_RunWorkerCompleted;  
  23.       bw.RunWorkerAsync("Hello to worker");  
  24.       Console.WriteLine("Press /"C/" to cancel");  
  25.   
  26.       while (true)  
  27.       {  
  28.         //按C取消  
  29.         if (Console.ReadKey(true).Key == ConsoleKey.C)  
  30.         {  
  31.           if (bw.IsBusy)  
  32.             bw.CancelAsync(); //提交取消命令,但还未取消  
  33.           else { break; }  
  34.         }  
  35.       }  
  36.       //Console.ReadLine();  
  37.     }  
  38.   
  39.     static void bw_DoWork(object sender, DoWorkEventArgs e)  
  40.     {  
  41.       Console.WriteLine(e.Argument);  
  42.       for (int i = 0; i <= 100; i += 1)  
  43.       {  
  44.         //判断是否取消操作  
  45.         if (bw.CancellationPending)  
  46.         {  
  47.           e.Cancel = true//这里才真正取消  
  48.           return;  
  49.         }  
  50.         //传递给ProgressChanged  
  51.         bw.ReportProgress(i);  
  52.         Thread.Sleep(100);  
  53.         e.Result = i;  
  54.       }  
  55.       // 最终传递给RunWorkerCopmleted   
  56.     }  
  57.   
  58.     static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
  59.     {  
  60.       if (e.Cancelled)  
  61.         Console.WriteLine("You cancelled!");  
  62.       else if (e.Error != null)  
  63.         Console.WriteLine("Worker exception: " + e.Error.ToString());  
  64.       else  
  65.       {  
  66.         Console.WriteLine("Complete - " + e.Result);      // 从 DoWork   
  67.       }  
  68.     }  
  69.   
  70.     static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)  
  71.     {  
  72.       Console.Write("{0,3}/b/b/b", e.ProgressPercentage);  
  73.     }  
  74.   }  
  75. }  
  76. #endregion  

 

方法2中DoWork事件中执行的是一个比较耗时的方法时该怎么办了.方法中没有循环无法判断用户是否执行了取消操作!

 

那么这里就要用到[异步编程模式],在执行一个比较耗时的方法时,代码还能继续向下运行.....!

 

请看下面代码-----------此代码是本人自己写的

  1. BackgroundWorker bgworker = new BackgroundWorker();  
  2. gworker.WorkerSupportsCancellation = true//是否支持异步取消  如果要取消操作必须设置true  
  3.      bgworker.DoWork += new DoWorkEventHandler(this.bgworker_DoWork);  
  4.      bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.bgworker_RunWorkerCompleted);  
  5.   
  6.    private void begin_Click(object sender, EventArgs e)  
  7.    {  
  8.      //开始  
  9.       if(!bgworker.IsBusy)  
  10.        {  
  11.            bgworker.RunWorkerAsync(); //开始操作  
  12.         }  
  13.    }  
  14.   
  15.    private void end_Click(object sender, EventArgs e)  
  16.    {  
  17.      //开始取消  
  18.      if (bgworker.IsBusy) //是否在运行异步操作  
  19.      {  
  20.        bgworker.CancelAsync(); //(是)提交取消命令  
  21.      }  
  22.    }  
  23.   
  24.    private void bgworker_DoWork(object sender, DoWorkEventArgs e)  
  25.    {  
  26.      //Sql语句 查询的数据很多  
  27.      string sql = "select * from table";    
  28.   
  29.      //绑定委托要执行的方法  
  30.      Del_DoWork work = new Del_DoWork(ReturnDataTable);  
  31.   
  32.      //开始异步执行(ReturnDataTable)方法  
  33.      IAsyncResult ret = work.BeginInvoke(sql, nullnull);   
  34.        
  35.      //(异步编程模式好久就是在执行一个很耗时的方法(ReturnDataTable)时,还能向下继续运行代码)  
  36.   
  37.      //接着运行下面的while循环,  
  38.      //判断异步操作是否完成  
  39.      while (!ret.IsCompleted)    
  40.      {  
  41.        //没完成  
  42.        //判断是否取消了backgroundworker异步操作  
  43.        if (bgworker.CancellationPending)   
  44.        {  
  45.          //如何是  马上取消backgroundwork操作(这个地方才是真正取消)  
  46.          e.Cancel = true;   
  47.          return;  
  48.        }  
  49.      }  
  50.      e.Result = work.EndInvoke(ret); //返回查询结果 赋值给e.Result  
  51.    }  
  52.   
  53.    private delegate DataTable Del_DoWork(string sql);  //创建一个委托  
  54.    /// <summary>  
  55.    /// 查询数据库表--------一个很耗时的方法  
  56.    /// </summary>  
  57.    /// <param name="sql"></param>  
  58.    /// <returns></returns>  
  59.    private DataTable ReturnDataTable(string sql)  
  60.    {  
  61.      DataTable table = new DataTable();  
  62.      SqlConnection conn = new SqlConnection("Server............");  
  63.      //.....................(省略)  
  64.      return table;  
  65.    }  
  66.   
  67.    private void bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
  68.    {  
  69.      if (e.Cancelled)  
  70.      {  
  71.        MessageBox.Show("您取消了操作!");  
  72.      }  
  73.      else if (e.Error != null)  
  74.      {  
  75.        MessageBox.Show("出现错误!");  
  76.      }  
  77.      else  
  78.      {  
  79.        DataTable table = e.Result as DataTable;  
  80.        if (table != null)  
  81.        {  
  82.          //得到数据,进行显示操作  
  83.          //dataGridView1.DataSource = table;  
  84.        }  
  85.      }  
  86.    }  

 

 

我这里主要是方法2,在很多情况下,我们的DoWork事件都是执行一个方法,而不是一个循环....如果你也遇到要执行一个耗时方法,又要取消操作的话,请用方法2吧!

http://blog.csdn.net/wxm3630478/article/details/6126459

posted @ 2011-11-28 11:25  qb371  阅读(358)  评论(0编辑  收藏  举报