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

posted @ 2011-08-27 14:47  therockthe  阅读(6242)  评论(6编辑  收藏  举报