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);
- //开始异步执行(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吧!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义