异步委托方式取消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; ...
随机推荐
- Java学习,从入门到放弃(一)SpringMVC+Maven+Mybits 多种数据库配置(mysql+sqlserver)AOP方式
多数据库配置需求有两种,一种是因为项目太大,访问量太高,不得不分布多个数据库减轻访问压力,比较多的应用就是读写分离:另一种就是原本不同的两个数据库业务现在要整合到一起,甚至连数据库都不一样,一个mys ...
- python 多线程模板简单实现
#-*- encoding: UTF-8 -*- #编码声明 import threading,Queue,os import time #导入方法模块 def main(inargs): work_ ...
- 1. Arduino对第三方开发板的支持
Arduino对第三方开发板也有支持接口,需要手动添加,我们以STM32系列为例,说明添加过程. 目前st的官方提供的一系列板子都支持Arduino,可能是Arduino-IDE更新太慢,目前版本没有 ...
- C++大数运算模板
#include<iostream> #include<cstring> #include<cstdio> #include<iomanip> #inc ...
- Hue,Oozie运行sqoop找不到驱动解决办法
一.前言 平台:CDH 5.13.0 公司在客户那边有个项目需要部署cloudera平台,部署的时候,在这个版本的cdh中,除了基本组件,还选了sqoop2作为数据传输工具,希望能在Oozie中通过工 ...
- InnoDB一定会在索引中加上主键吗?
先回答问题,是的. 故事, 如下图,今天查看慢sql发现同事在建索引的时候竟然包含了主键,第一感觉这种姿势不对. 我记得很多文章都说过二级索引会自动带上主键,为什么还有人这么操作,后来差了些资料,如下 ...
- hexo 个人博客搭建
Hexo 小插曲介绍 虽然标题是第一次写博客. 但是我这个困难户至少挣扎了1年多了, 一直下不去手.今天可算是开了个头. 贵在坚持吧 抽时间介绍我的hexo安装历程吧,今天实在是有点困了,要睡觉了. ...
- 第1章:LeetCode--基础部分
LeetCode刷题指导(不能只实现功能就行需要尽量写最优解): 不可能刷遍所有题,只能通过刷题来恢复写代码的功力,熟悉常用算法(暴力算法.冒泡排序/快速排序.strStr KMP算法.二叉树遍历DF ...
- Django项目配置参数大全
数据库的配置 配置文件: settings.pyDATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NA ...
- wx存储数据到本地及本地获取
官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html 存到本地就是存到手机的 ...