Winform 进度条弹窗和任务控制

Winform 进度条弹窗和任务控制

目录

Winform 进度条弹窗和任务控制

一、弹窗前台

二、弹窗后台

三、使用方法

四、效果展示和代码地址

独立观察员 2020 年 11 月 17 日

 

最近要给一个 Winform 项目添加功能,需要一个能显示进度条的弹窗,还要求能够中止任务,所以就做了一个,在此做个记录总结。虽然用的是比较老的 Winform 技术,不过其中的原理都是相通的。

 

一、弹窗前台

首先提供一个 Winform 控件居中的小技巧:

将控件放在 TableLayoutPanel 容器中,然后将控件的 Anchor 属性设置为 None,这样控件就能在容器中居中了:

 

将容器的 Anchor 属性设置为 Top, Left, Right,这样容器就能随着窗口左右拉伸了:

 

最终弹窗界面如下:

 

使用了 CSkin 界面库(v16.1.14.3),(注意:如果拖拽 dll 到工具箱拖不了,可以使用右键复制粘贴的方式),窗体继承 Skin_DevExpress,进度条使用 SkinProgressBar,按钮使用 SkinButton,主要是使用了一些圆角效果:

 

二、弹窗后台

先添加两个事件供外界订阅,分别为窗体载入时触发的执行操作事件,和点击中止按钮后触发的终止操作事件:

/// <summary>
/// 执行操作事件
/// </summary>
public event Action OperateAction;/// <summary>
/// 终止操作事件
/// </summary>
public event Action AbortAction;/// <summary>
/// 中止按钮点击事件
/// </summary>
private void btn_Abort_Click(object sender, EventArgs e)
{AbortAction?.Invoke();DialogResult = DialogResult.Abort;//Close (); // 不需要手动关闭;
}/// <summary>
/// 窗体载入事件
/// </summary>
private void FormProgressDialog_Load(object sender, EventArgs e)
{Task.Factory.StartNew(() =>{OperateAction?.Invoke();DialogResult = DialogResult.OK;});
}

 

点击中止按钮后还将弹窗结果设为 Abort,会自动关闭弹窗;而业务操作正常执行完毕,弹窗结果为 OK。

 

供外界设置文本信息以及进度条进度的方法如下:

/// <summary>
/// 设置显示信息 (值为 null 时保持不变)
/// </summary>
/// <param name="rtfTitleContent"> 富文本格式的标题内容 </param>
/// <param name="totalMessage"> 总体消息 </param>
/// <param name="currentMessage"> 当前消息 </param>
public void SetInfo(string rtfTitleContent = null, string totalMessage = null, string currentMessage = null)
{if (rtfTitleContent != null) rtb_Title.Rtf = rtfTitleContent;if (totalMessage != null) lbl_Total.Text = totalMessage;if (currentMessage != null) lbl_Current.Text = currentMessage;
}/// <summary>
/// 设置进度
/// </summary>
/// <param name="currentValue"> 当前数值 </param>
/// <param name="totalValue"> 总数值 </param>
public void SetProsess(double currentValue, double totalValue)
{try{progressBar.Value = (int)(currentValue / totalValue * 100);}catch (Exception ex){Console.WriteLine(ex);}
}

 

剩下就是两个设置富文本框 RichTextBox 的方法,包括设置彩色内容和隐藏 RichTextBox 光标的方法,文末会给出代码地址,此处不再赘述。

 

三、使用方法

首先映入眼帘的是两个成员变量,一个是用于任务取消的 CancellationTokenSource 对象,另一个是用于线程同步的 AutoResetEvent 对象(用于取消任务后的一些信息同步);然后是主测试方法(一个按钮点击事件方法)中的一些信息设置:

 

然后设置 CancellationTokenSource 对象的 Token,给它注册一个取消任务时调用的委托方法,里面先等待同步信号结果再进行本次执行结果的判断:

 

接下来订阅弹窗中的那两个事件,在执行操作事件中开启任务,并传递 Token;在中止事件中停止任务:

 

需要注意的是,停止任务后,任务内部并不会自己停止,需要判断 Token 的 IsCancellationRequested 字段来决定相应的操作,比如结束循环。然后,因为在之前注册的取消的委托方法中,进行了等待,所以我们在执行完业务方法(BusinessMethod)并设置好相关状态值后,需要判断任务是否取消,如果取消,说明注册的取消的委托方法中已经在等待了,所以要调用 Set () 进行放行。

 

有人可能就会问了,foreach 循环开始时不是判断过是否取消了吗?这里怎么又判断?这是因为,比如在一轮循环中,已经执行过了开头的是否已取消的判断(IsCancellationRequested 为 false),开始执行耗时的业务方法了,此时用户点击中止按钮,IsCancellationRequested 被置为 true,所以业务方法执行后再次判断会得到最新的状态,然后,循环将在下一轮开始时结束。

 

另外,由于实际使用这个的项目是 .NET 4.0 框架,所以 Task 的一些方法没有,大家用新框架的话可以使用新方法。或者使用 Microsoft.Bcl.Async 包,然后使用 TaskEx

 

继续流程,接下来以模态框方式弹出窗口,并获取结果。业务处理方法中模拟了耗时操作并返回是否成功。

 

最后给出完整代码:

#region 测试任务进度条弹窗private CancellationTokenSource _Cts; // 任务取消令牌;
private AutoResetEvent _AutoResetEvent = new AutoResetEvent(false);// 参数传 false,则 WaitOne 时阻塞等待;/// <summary>
/// 测试任务进度弹窗
/// </summary>
private void BtnProgressDialog_Click(object sender, EventArgs e)
{_AutoResetEvent.Reset();string businessName = "业务 1";FormProgressDialog progressWindow = new FormProgressDialog(){Text = "任务处理窗口",};progressWindow.SetColorfulTitle("业务 1", Color.DarkOrange, true);progressWindow.SetColorfulTitle("正在执行中......", Color.Black);progressWindow.SetInfo(null, "", "");List<string> orders = new List<string>(){"订单 1", "订单 2", "订单 3", "订单 4", "订单 5" }; // 业务数据;List<string> leftList = orders.Select(x => x).ToList(); // 剩余(未处理)数据;int successCount = 0; // 成功数量;_Cts = new CancellationTokenSource();// 注册一个将在取消此 CancellationToken 时调用的委托;_Cts.Token.Register(async () =>{ShowInfo("操作终止");await Task.Run(() =>{_AutoResetEvent.WaitOne(1000 * 5); // 等待有可能还在执行的业务方法;if (successCount < orders.Count){ShowInfo($"{businessName} 有 {orders.Count - successCount} 项任务被终止,可在消息框中查看具体项。");foreach (var leftName in leftList){ShowInfo($"【{businessName}】的【{leftName}】执行失败,失败原因:【手动终止】。");}}});});progressWindow.OperateAction += () =>{Task task = new Task(() =>{foreach (var order in orders){// 判断是否被取消;if (_Cts.Token.IsCancellationRequested){break;}progressWindow.TryBeginInvoke(new Action(() =>{progressWindow.SetInfo(null, $" 共 {orders.Count} 项,已执行 {successCount} 项 ", $" 当前正在执行:{order}");}));if (BusinessMethod(order, businessName)){successCount++;leftList.RemoveAll(x => x == order);if (_Cts.Token.IsCancellationRequested){_AutoResetEvent.Set(); // 放行 Register 委托处的等待;}}progressWindow.TryBeginInvoke(new Action(() =>{progressWindow.SetProsess(orders.IndexOf(order) + 1, orders.Count);}));}}, _Cts.Token);task.Start();task.Wait();};progressWindow.AbortAction += () =>{_Cts.Cancel();};var result = progressWindow.ShowDialog();int leftCount = orders.Count - successCount;if (result == DialogResult.OK || leftCount <= 0){ShowInfo($"{businessName} 整体完成。");}else if (result == DialogResult.Abort){// 移到 _Cts.Token.Register 处一起判断,不然数目可能不准;//ShowInfo ($"{businessName} 有 {leftCount} 项任务被终止,可在消息框中查看具体项。");}
}/// <summary>
/// 业务处理方法
/// </summary>
private bool BusinessMethod(string order, string businessName)
{string errStr = $"【{businessName}】的 {order} 任务失败,失败原因:";// 测试Thread.Sleep(1000 * 2);try{// 业务方法;ShowInfo($"【{businessName}】的 {order} 任务执行成功。");return true;}catch (Exception ex){ShowInfo($"{errStr}{ex.Message}");}return false;
}#endregion

 

四、效果展示和代码地址

正常执行(动图):

 

中止执行(动图):

 

代码地址:https://gitee.com/dlgcy/Practice/tree/master/WinFormPractice

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言prime函数怎么用_C语言 要发就发

点击上方“蓝字”关注我们愉快的一天&#xff0c;不得不做的三件事&#xff1a;种田&#xff0c;锄地&#xff0c;整代码&#xff01;&#xff01;&#xff01;【题目】“1898——要发就发”。请将不超过1993的所有素数从小到大排成第一行&#xff0c;第二行上的每个数都等于它…

linux如何使用vnc远程登录,如何使用Xmanager及VNC登录远程桌面

如何调用远程桌面&#xff0c;比较常见的有两种方式&#xff1a;Xmanager及VNC正好今天鼓捣了一下&#xff0c;特整理如下&#xff1a;XmanagerXmanager的调用也有两种方式&#xff1a;一、直接在Xshell中调用这时需设置会话属性&#xff0c;如下图所示&#xff0c;需在“隧道”…

python自然语言处理_python

chinese-xinhua/ | - data/ 汉字例子&#xff1a; { "word": "吖", "oldword": "吖", "strokes": "6", "pinyin": "ā", "radicals": "口", "explanation": &…

别在.NET死忠粉面前黑.NET5,它未来可期!

期盼已久的.NET5&#xff0c;终于在11月11日正式发布&#xff0c;整个.NET社区都为之沸腾&#xff0c;知乎、博客园、QQ群、微信群&#xff0c;随处可见.NET5 的热议&#xff0c;作为.NET死忠粉&#xff0c;我也挺兴奋的。然而一片欢歌笑语中总有一些很不和谐的声音&#xff0c…

c#物联网_C# 基础知识系列- 16 开发工具篇

0. 前言 这是C# 基础知识系列的最后一个内容讲解篇&#xff0c;下一篇是基础知识-实战篇。这一篇主要讲解一下C#程序的结构和主要编程工具。 1. 工具 工欲善其事必先利其器&#xff0c;在实际动手之前我们先来看看想要编写一套C#程序需要做哪些准备吧。 1.1 选择 C# 的sdk在之前…

接口幂等设计探索实践

幂等性原本是数学上的概念&#xff0c;即使公式&#xff1a;f(x)f(f(x)) 能够成立的数学性质。用在编程领域&#xff0c;则意为对同一个系统&#xff0c;使用同样的条件&#xff0c;一次请求和重复的多次请求对系统资源的影响是一致的、或者说是符合预期的。背景稳定性设计第一…

Windows 7 安装 .NET 5 / .NET Core 3.1 环境的方法和依赖文件

随着 .NET 5 正式版的发布&#xff0c;越来越多的人开始向 .NET 5 、.NET Core 平台迁移。尽管微软已经在 2020 年 1 月 14 日停止了对 Windows 7 的支持&#xff0c;但仍有大批客户的操作系统对 Windows 7 恋恋不舍。为此&#xff0c;我们需要解决 .NET 5 运行时&#xff08;R…

easyui 动态设置单元格控件_动态显示最大最小值的折线图

小伙伴们好啊&#xff0c;今天和大家分享一个图表有关的知识。折线图想必大家已经司空见惯&#xff0c;今天就要在简单的折线上&#xff0c;做出不简单的效果。用动态折线图&#xff0c;展示一周销售的变化&#xff0c;并且自动突出最大最小值。1、准备数据源以某家水果店1月份…

WebBenchmark动态测试Webapi

在编写Webapi测试用例的时候都是定义固定的测试数据&#xff0c;但这样的测试只能针对单一数据。为了更好的模拟实际情况&#xff0c;往往需要进行动态数据测试&#xff1b;通过动态数据测试可以更好的测出服务在不同数据情况下的处理能力。WebBenchmark支持动态数据函数&#…

linux开发需要学习什么,linux开发需要掌握哪些知识?

原标题&#xff1a;linux开发需要掌握哪些知识&#xff1f;嵌入式linux开发的应用是非常广泛的。而且linux是开源的&#xff0c;各种技术也是非常成熟的。不过很多初学者在学习linux开发过程中感觉非常难&#xff0c;那么对于linux开发需要掌握哪些知识呢&#xff1f;1.Linux是…

csv 字符串_python3从零学习-5.5.1、CSV 文件读写

源代码&#xff1a; Lib/csv.py模块内容csv 模块定义了以下函数&#xff1a;csv.reader(csvfile, dialectexcel, **fmtparams)返回一个 reader 对象&#xff0c;该对象将逐行遍历 csvfile。csvfile 可以是任何对象&#xff0c;只要这个对象支持 iterator 协议并在每次调用 __ne…

持续交付三:动手自动化“开发”—“测试”

前两篇博文中提到Development,QA,Staging,Production四个环境&#xff0c;也说明了源代码的分支和四个环境的对应关系&#xff0c;本篇博文聊一下&#xff0c;怎么把源码自动化发布到对应的环境中。市面上主流的DevOpt工具都支持这些功能&#xff0c;github,gitlab&#xff0c;…

使用WebBenchmark对webapi进行管理和性能测试

WebBenchmark是基于beetlex开发的webapi管理和性能测试软件&#xff0c;最新版本1.0.3可以独立运行在linux/windows中&#xff0c;并不再需要安装.net core运行环境。部署可以通过以下地址下载最新版本:https://github.com/IKende/WebBenchmark可以根据需要下载linux64或win64运…

三维叉乘怎么算_奇技淫巧系列:向量叉乘

​一般我们在解决立体几何题目时会选择建立坐标系&#xff0c;因为这样做比较保险也有固定套路。很多时候这些题目要求你计算某一个面的法向量&#xff08;normal vector&#xff09;&#xff0c;这在高中阶段也是有固定方法的&#xff0c;我们这里想要介绍的是一种更高级也更迅…

g++ linux intel 汇编,g++ linux

目标&#xff1a;运行C代码example&#xff1a;有func.h,func.cpp, main.cpp- .h无需编译&#xff0c;但.h中函数实现的地方需要编译(func.cpp)- 逻辑&#xff1a;cpp各自生成可执行文件(.o),再进行链接g -c func.cppg -c main.cppg main.o func.o -o test或者直接&#xff1a;…

听说容器正在吃掉整个软件世界?

过去几年&#xff0c;以 docker、kubernetes 为代表的容器技术已发展为一项通用技术&#xff0c;BAT、滴滴、京东、头条等大厂&#xff0c;都争相把容器和 k8s 项目作为技术重心&#xff0c;试图“放长线钓大鱼”。就说腾讯吧&#xff0c;目前基本所有业务都跑在云上&#xff0…

linux 短信功能,Android调用系统短信功能发送短信

Android调用系统短信功能发送短信有两种方法:第一种&#xff0c;设定发送的号码&#xff0c;和内容&#xff0c;界面没有联系人&#xff0c;群组组等按钮&#xff0c;如下图所示&#xff1a;代码如下&#xff1a;Uri smsToUri Uri.parse("smsto:114");// 联系人地址…

bcm943602cs蓝牙用不了_原来手机的蓝牙功能这么强大!除了连接耳机,还有这六大实用功能...

蓝牙是手机上的一个普通功能&#xff0c;基本上所有的手机里都有它&#xff0c;原先它的作用很有限&#xff0c;只是用来传输数据&#xff0c;但由于速度太慢&#xff0c;最后也是被软件所淘汰&#xff0c;慢慢的可以用来连接耳机&#xff0c;这也是博主用的比较多的一个功能&a…

数据结构——表达式求值(中序)

表达式求值&#xff08;中序&#xff09; 实验二 基于栈的中缀算术表达式求值 【实验目的】 1.掌握栈的基本操作算法的实现,包括栈初始化、进栈、出栈、取栈顶元素等。 2.掌握利用栈实现中缀表达式求值的算法。 【实验内容】 问题描述 输入一个中缀算术表达式,求解表达式的值。…

msdn画圆弧函数_画直线不简单!python-matplotlib告诉你为什么

1 说明&#xff1a;1.1 python的matplotlib画直线&#xff0c;看似简单&#xff0c;其实很难&#xff0c;从简单到复杂&#xff0c;逐步深入&#xff0c;小白秒懂。1.2 内容&#xff1a;画直线&#xff0c;画圆&#xff0c;画圆点&#xff0c;动画的单摆和圆套圆&#xff0c;好…