异步委托方式取消BackGroundWorker执行无循环的耗时方法
边学习边分享,纯属抛砖引玉。
线程的一个好处是异步的执行操作,在winform中,很多耗时操作执行时,为优化用户体验,避免长时间等待,从而运用线程技术异步的执行耗时操作,但不会阻塞主线程。
最近系统很多耗时查询导致体验很差,于是想到了用BackGroundWorker异步处理。而且要支持某些耗时达到几十秒的操作,可以取消。
BackGroundWorker有CancelAsync()这个方法。该方法只会将BackGroundWorker的CancellationPending属性设为true,但不会实际终止线程!网上找了些资料,代码如下
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{ for (int i = ; i < ; i++)
{
if (backgroundWorker1.CancellationPending) {
e.Cancel = true;
return;
}
}
}
即在doWork事件中,不停的循环判断是否执行了取消操作。这种适用于执行多次方法时,而且无法在某个方法执行时将线程取消。如果我doWork事件里,没有for循环,而是一次耗时的数据访问操作,那这样的处理没有任何意义。
于是在下想到,可以在doWork事件里做如下处理
1.异步的去执行耗时操作。
2.while监视异步耗时操作是否完成,只要未完成就一直循环。循环内部判断是否执行了取消操作。如果执行了取消操作,则终止线程。代码如下
private delegate int LongTimeDele();
private bool isComplated=false;
private int result=;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
this.BeginInvoke(new LongTimeDele(()=>{
Thread.Sleep();////模拟耗时
for (int i = ; i < ; i++)
{
result++;
}
isComplated=true;
})); while(!isComplated){ if (backgroundWorker1.CancellationPending) {
e.Cancel = true;
return;
}
}
}
试验之后,不知何故在this.BeginInvoke中的循环会阻塞主线程! 即界面卡主不动了,BeginInvoke应该是一步执行的,在下功力尚浅,不知何故,还请高手指教。
于是想到了异步委托。直接上代码


cs代码
public partial class BackgroundWorkerTest : Form
{ public BackgroundWorkerTest()
{
InitializeComponent(); }
/// <summary>
/// 建立一个委托,用来调用耗时操作。返回值是int,当然也可以是string、DataTable.....
/// </summary>
/// <returns></returns>
private delegate int LongTimeDele(); /// <summary>
/// doWork事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{ //声明一个委托的实例
var waitHandller = new LongTimeDele(
() =>
{
//线程休眠10秒,模拟耗时操作
Thread.Sleep();
var sumResult = ;
for (int i = ; i < ; i++)
{
sumResult++;
}
return sumResult;
});
//BeginInvoke,异步的去执行委托实例里的匿名方法。该方法返回的是一个IAsyncResult。返回值的状态会实时更新!
var isa = waitHandller.BeginInvoke(null, null);
//由于上面是异步,所以while的代码不会等待上面操作完成后执行,二者几乎同时执行
//判断isa是否完成了,未完成的话(等待耗时操作)执行内部代码
while (!isa.IsCompleted)
{
//判断CancellationPending属性是否为true。如果你点击了取消button,这个属性就变成true了
if (backgroundWorker1.CancellationPending)
{
//取消操作
e.Cancel = true;
return;
}
}
//能执行到这里就说明操作完成了,把结果放进e中,传递给RunWorkerCompleted事件
e.Result = waitHandller.EndInvoke(isa); } /// <summary>
/// backgroundWorker执行完毕时事件,无论正常完成还是取消都会出发该事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//只要不是类型EventArgs,你想要的数据e里面应有尽有!判断是否取消了操作
if (e.Cancelled)
{
MessageBox.Show("操作已取消");
return; }
//否则显示结果
MessageBox.Show(e.Result.ToString());
} /// <summary>
/// 取消按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCancle_Click(object sender, EventArgs e)
{
//调用 backgroundWorker的CancelAsync()方法,该方法只会将CancellationPending属性设为true,并不会实际结束线程执行
backgroundWorker1.CancelAsync();
} /// <summary>
/// 开始按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
//判断线程是否繁忙
if (backgroundWorker1.IsBusy)
{
MessageBox.Show("系统繁忙");
return;
}
//空闲开始异步操作
backgroundWorker1.RunWorkerAsync();
}
}
异步委托方式取消BackGroundWorker执行无循环的耗时方法的更多相关文章
- 使用getScript()方法异步加载并执行js文件
使用getScript()方法异步加载并执行js文件 使用getScript()方法异步请求并执行服务器中的JavaScript格式的文件,它的调用格式如下所示: jQuery.getScript(u ...
- iOS 设置 延迟执行 与 取消延迟执行 方法 以及对 run loop 初步认识
之前开发过程中经常会有需求会使用 NSObject中的"performSelector:withObject:afterDelay:"做方法延迟执行的处理, 但是 还没有什么地方需 ...
- C# 如何取消BackgroundWorker异步操作
BackgroundWorker 在执行DoWork事件时该如何取消呢? 方法1 DoWork 执行一个(耗时)循环 方法2 DoWork执行一个(耗时)方法[注:方法没有循环] 见代码: 方法1中D ...
- 在Winform开发中,使用Async-Awati异步任务处理代替BackgroundWorker
在Winform开发中有时候我们为了不影响主UI线程的处理,以前我们使用后台线程BackgroundWorker来处理一些任务操作,不过随着异步处理提供的便利性,我们可以使用Async-Awati异步 ...
- js同步、异步、回调的执行顺序以及闭包的理解
首先,记住同步第一.异步第二.回调最末的口诀 公式表达:同步=>异步=>回调 看一道经典的面试题: for (var i = 0; i < 5; i++) { setTimeout( ...
- LazyMay:实现同步和异步任务的顺序执行
在掘金看到的文章,流程控制同步和异步任务的顺序执行,收益匪浅,工作中能用到. 1.实现以下效果 实现一个LazyMan,可以按照以下方式调用: LazyMan(“Hank”)输出: Hi! This ...
- js的for循环中出现异步函数,回调引用的循环值始终是最后的值
一.问题 今天工作中解决bug发现是由“for循环的异步函数,回调引用的循环值始终是最后的值”的现象导致的,如: for (var i = 0; i < files.length; i++) { ...
- 矩阵之间无循环计算L2距离
实现两个矩阵的无循环计算欧氏距离 Euclidean distance navigation: 1.问题描述 2.解决方法 1.问题来源 kNN算法中会计算两个矩阵的距离 可以使用循环的方法来实现,效 ...
- 异步委托(APM)使用Func异步操作,处理耗时操作
使用委托进行异步操作,处理一些耗时操作,防止主线程阻塞 使用例子: using System; using System.Collections.Generic; using System.Linq; ...
随机推荐
- robot:循环遍历数据库查询结果是否满足要求
使用list类型变量@{}接收查询结果,再for循环遍历每行数据,取出需要比较的数值
- Ubuntu 新装服务器部署流程
1.设定时区 rm -f /etc/localtime cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 2.配置apt-get源 sed -i ...
- 安装Windows和Ubuntu双系统
发现关注消息 安装Windows和Ubuntu双系统 安装Windows和Ubuntu双系统 0.552016.12.10 15:54:41字数 2101阅读 6644 这几天开始动手做毕设啦 ...
- Java基础:类文件结构及类加载
Class文件结构 魔数 4bits 确定该文件是否是可接受的Class文件(0xCAFEBABE) 版本号 4bits 包括次版本号和主版本号 常量池 包括字面量(文本字符串,声明为final的常量 ...
- 【CUDA开发】CUDA面内存拷贝用法总结
[CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...
- 初始NLTK
NLTK官网:链接 Natural Language Toolkit NLTK corpora and lexical resources such as WordNet, along with a ...
- PAT(B) 1033 旧键盘打字(C) 字符
题目链接:1033 旧键盘打字 (20 point(s)) 题目描述 旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是 ...
- 【Qt】Qt5.12连接MySQl5.7(亲自测试成功)
目录 00. 目录 01. Qt5.12连接MySQL5.7测试代码 02. Qt5.12连接MySQL5.7问题描述 03. 解决办法 04. 结果测试 05. 打赏 00. 目录 01. Qt5. ...
- Python完成迪杰斯特拉算法并生成最短路径
def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path……") path=[ ...
- ubuntu下tftp的安装、配置、使用
1. 安装 sudo apt-get install tftp-hpa tftpd-hpa -y 2. 配置 sudo vi /etc/default/tftpd-hpa #/etc/default/ ...