zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)
    「BZOJ1433」[ZJOI2009] 假期的宿舍(二分图,网络流)
    BZOJ 1061 [Noi2008]志愿者招募(费用流)
    [BZOJ2879][Noi2012]美食节(费用流)
    bzoj 1834 [ZJOI2010] network 网络扩容(费用流)
    BZOJ2668:[CQOI2012]交换棋子(费用流)
    bzoj1070【SCOI2007】修车(费用流)
    【BZOJ 1877】 [SDOI2009]晨跑(费用流)
    SQLite_Home
    GeoMesa-单机搭建
  • 原文地址:https://www.cnblogs.com/mq0036/p/10872293.html
Copyright © 2011-2022 走看看