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);
- //开始异步执行(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吧!
http://blog.youkuaiyun.com/wxm3630478/article/details/6126459