C# 如何取消BackgroundWorker异步操作

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

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

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

见代码:

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

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

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

复制代码
#region 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 
using System.Threading; 
using System.Text.RegularExpressions; 
 
namespace ConsoleBackgroundworker 
{ 
  class Program 
  { 
    static BackgroundWorker bw; 
    static void Main() 
    { 
      bw = new BackgroundWorker(); 
      bw.WorkerReportsProgress = true; 
      bw.WorkerSupportsCancellation = true; 
      bw.DoWork += bw_DoWork; 
      bw.ProgressChanged += bw_ProgressChanged; 
      bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
      bw.RunWorkerAsync("Hello to worker"); 
      Console.WriteLine("Press /"C/" to cancel"); 
 
      while (true) 
      { 
        //按C取消 
        if (Console.ReadKey(true).Key == ConsoleKey.C) 
        { 
          if (bw.IsBusy) 
            bw.CancelAsync(); //提交取消命令,但还未取消 
          else { break; } 
        } 
      } 
      //Console.ReadLine(); 
    } 
 
    static void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
      Console.WriteLine(e.Argument); 
      for (int i = 0; i <= 100; i += 1) 
      { 
        //判断是否取消操作 
        if (bw.CancellationPending) 
        { 
          e.Cancel = true; //这里才真正取消 
          return; 
        } 
        //传递给ProgressChanged 
        bw.ReportProgress(i); 
        Thread.Sleep(100); 
        e.Result = i; 
      } 
      // 最终传递给RunWorkerCopmleted  
    } 
 
    static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
      if (e.Cancelled) 
        Console.WriteLine("You cancelled!"); 
      else if (e.Error != null) 
        Console.WriteLine("Worker exception: " + e.Error.ToString()); 
      else 
      { 
        Console.WriteLine("Complete - " + e.Result);      // 从 DoWork 传过来的参数 
      } 
    } 
 
    static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
      Console.Write("{0,3}/b/b/b", e.ProgressPercentage); 
    } 
  } 
} 
#endregion
复制代码

 

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

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

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

复制代码
BackgroundWorker bgworker = new BackgroundWorker(); 
gworker.WorkerSupportsCancellation = true; //是否支持异步取消  如果要取消操作必须设置true 
     bgworker.DoWork += new DoWorkEventHandler(this.bgworker_DoWork); 
     bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.bgworker_RunWorkerCompleted); 
 
   private void begin_Click(object sender, EventArgs e) 
   { 
     //开始 
      if(!bgworker.IsBusy) 
       { 
           bgworker.RunWorkerAsync(); //开始操作 
        } 
   } 
 
   private void end_Click(object sender, EventArgs e) 
   { 
     //开始取消 
     if (bgworker.IsBusy) //是否在运行异步操作 
     { 
       bgworker.CancelAsync(); //(是)提交取消命令 
     } 
   } 
 
   private void bgworker_DoWork(object sender, DoWorkEventArgs e) 
   { 
     //Sql语句 查询的数据很多 
     string sql = "select * from table";   
 
     //绑定委托要执行的方法 
     Del_DoWork work = new Del_DoWork(ReturnDataTable); //可以使用:delegate、Action、Func、predicate 等,具体可参考:C#委托的介绍(delegate、Action、Func、predicate)委托的N种写法
 
     //开始异步执行(ReturnDataTable)方法 
     IAsyncResult ret = work.BeginInvoke(sql, null, null);  
      
     //(异步编程模式好久就是在执行一个很耗时的方法(ReturnDataTable)时,还能向下继续运行代码) 
 
     //接着运行下面的while循环, 
     //判断异步操作是否完成 
     while (!ret.IsCompleted)   
     { 
       //没完成 
       //判断是否取消了backgroundworker异步操作 
       if (bgworker.CancellationPending)  
       { 
         //如何是  马上取消backgroundwork操作(这个地方才是真正取消) 
         e.Cancel = true;  
         return; 
       } 
     } 
     e.Result = work.EndInvoke(ret); //返回查询结果 赋值给e.Result 
   } 
 
   private delegate DataTable Del_DoWork(string sql);  //创建一个委托 
   /// <summary> 
   /// 查询数据库表--------一个很耗时的方法 
   /// </summary> 
   /// <param name="sql"></param> 
   /// <returns></returns> 
   private DataTable ReturnDataTable(string sql) 
   { 
     DataTable table = new DataTable(); 
     SqlConnection conn = new SqlConnection("Server............"); 
     //.....................(省略) 
     return table; 
   } 
 
   private void bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
   { 
     if (e.Cancelled) 
     { 
       MessageBox.Show("您取消了操作!"); 
     } 
     else if (e.Error != null) 
     { 
       MessageBox.Show("出现错误!"); 
     } 
     else 
     { 
       DataTable table = e.Result as DataTable; 
       if (table != null) 
       { 
         //得到数据,进行显示操作 
         //dataGridView1.DataSource = table; 
       } 
     } 
   } 
复制代码

 

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

 

出处:https://www.cnblogs.com/therock/articles/2155511.html

https://www.cnblogs.com/MLGB/p/4027244.html

posted on   jack_Meng  阅读(1004)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2018-05-15 C#中Task的使用简单总结
2015-05-15 word 2007,以不同颜色突出显示文本的快捷键,highlight命令

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏

主题色彩