C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口
很多时候,我们需要在窗体中执行一些耗时比较久的任务。比如:循环处理某些文件,发送某些消息等。。。
单纯的依靠状态栏,用户体验不佳,按下功能按钮后得不到有效的提醒,小白用户绝对会电话给你说“我点了以后就没反应了...”。
因此,对于响应时间可能超过5秒以上的事件,有必要增加一个显眼的提示框(在屏幕中央,最好有动图,如果有需要的话还可以设置为模态)。
此实现大体分三部分(重点在于使用BGWK解决UI阻塞的问题):
1、设计好提醒页面(一个转圈圈的动图Image,一个状态文字Label,再加一个进度条):

如果不需要动图,则这个窗体无需编写代码。
2、显示这个窗体的代码,目前放在基类窗体中被子类窗体继承。
#region 显示应用程序作业状态
/// <summary>
/// 后台作业线程定义模板类
/// </summary>
protected class BgwkDef
{
public BackgroundWorker TagBgwk;
public Action RunningAction;
public int TProgMinimum = ;
public int TProgStep = ;
public int TProgMaximum = ;
public string RunningStatus;
} /// <summary>
/// 以指定的定义开始一个线程运行作业任务
/// </summary>
/// <param name="sBgwkDef"></param>
protected void BeginBgwork(BgwkDef sBgwkDef)
{
if (frmStatus == null)
{
frmStatus = new FrmStatus();
}
if (frmStatus != null)
{
frmStatus.ProgMain.Minimum = sBgwkDef.TProgMinimum;
frmStatus.ProgMain.Step = sBgwkDef.TProgStep;
frmStatus.ProgMain.Maximum = sBgwkDef.TProgMaximum;
frmStatus.TopLevel = false;
frmStatus.Parent = this;
frmStatus.Show();
frmStatus.BringToFront();
frmStatus.Left = (this.Width - frmStatus.Width) / ;
frmStatus.Top = (this.Height - frmStatus.Height) / - ;
}
if (sBgwkDef.RunningAction == null)
{
MyMsg.Warning("系统后台任务必须指定作业方法,请检查!");
return;
} BackgroundWorker tagBgwk = sBgwkDef.TagBgwk ?? new BackgroundWorker();
tagBgwk.WorkerSupportsCancellation = true;
tagBgwk.WorkerReportsProgress = true;
tagBgwk.DoWork -= BgwkBase1_DoWork;
tagBgwk.DoWork += BgwkBase1_DoWork;
tagBgwk.ProgressChanged -= BgwkBase1_ProgressChanged;
tagBgwk.ProgressChanged += BgwkBase1_ProgressChanged;
tagBgwk.RunWorkerCompleted -= BgwkBase1_RunWorkerCompleted;
tagBgwk.RunWorkerCompleted += BgwkBase1_RunWorkerCompleted;
tagBgwk.RunWorkerAsync(sBgwkDef.RunningAction);
} /// <summary>
/// 取消后台任务的当前作业
/// </summary>
/// <param name="tagBgwk"></param>
protected void CancelBgwork(BackgroundWorker tagBgwk)
{
tagBgwk.CancelAsync();
} /// <summary>
/// 在此事件中调用工作方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void BgwkBase1_DoWork(object sender, DoWorkEventArgs e)
{
((Action)e.Argument).Invoke();
} /// <summary>
/// 当后台任务运行进行进度报告时在状态窗口中显示状态
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void BgwkBase1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (frmStatus != null)
{
frmStatus.ProgMain.Value = e.ProgressPercentage > frmStatus.ProgMain.Maximum ? frmStatus.ProgMain.Maximum : e.ProgressPercentage;
frmStatus.ProgMain.PerformStep();
frmStatus.LabMessage.Text = e.UserState.ToString();
frmStatus.LabMessage.Refresh();
}
SetMainStatus(e.UserState.ToString());
} /// <summary>
/// 任务结束后(e.ProgressPercentage到100)关闭状态窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void BgwkBase1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
}
if (frmStatus != null)
{
frmStatus.Close();
frmStatus = null;
}
}
#endregion
3、调用第2步的显示方法的代码(实际工作场合)。
private void CmdExport_Click(object sender, EventArgs e)
{
//创建或匹配一个BackgroundWorker,初始化一个耗时任务
BackgroundWorker bgwk = new BackgroundWorker();
BgwkDef bgwkDef = new BgwkDef()
{
RunningAction = delegate () { ExportIvoice(bgwk); },
TagBgwk = bgwk
};
BeginBgwork(bgwkDef);
} //耗时比较久的工作任务方法
private void ExportIvoice(BackgroundWorker bgwk)
{
bgwk.ReportProgress(, "正在尝试导出到EXCEL...");
//打开Excel等操作
//各种操作......
if ("出错了")
{
CancelBgwork(bgwk);//取消任务
MyMsg.Exclamation("开启报表文件失败,请检查!");
return;
}
//继续运行......
//最后完成任务
bgwk.ReportProgress(, "导出成功!");
return;
}
这样,比较简单的就完成了一个友好提示功能。
C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口的更多相关文章
- winform设计一个登录界面和修改密码的界面-自动切换窗体(问题[已解] 望一起讨论)(技术改变世界-cnblog)
http://www.cnblogs.com/IAmBetter/archive/2012/01/14/2322156.html winform设计一个登录界面和修改密码的界面-自动切换窗体(问题[已 ...
- C# Winform下一个热插拔的MIS/MRP/ERP框架13(窗体基类)
作为一个ERP数据处理框架,大部分的开发场景都差不多. 理想中,对于通用数据处理,我的步骤如下: 1.为窗体指定数据来源(数据表/查询等): 2.拖入编辑控件,指定绑定字段: 3.结束. 为此,我设计 ...
- 设计一个较好的框架的难点之一--API兼容性的设计
设计一个好的框架和设计一个好的软件一样,需要考虑的方面很多,比如扩展性.性能.用户体验.稳健性等等,视不同的场景,每个点都可能导致成败,但他们通常并不是老板们关心的,因为在大部分情况下,他们通常都没有 ...
- 如何在asp.net中使用多线程及队列,异步处理一个耗时的任务(原创)
最近想在使用.net 的队列处理一些耗时的工作.经过考虑,需要先设计一个类,类中包含一个静态的队列.主要是写队列和读取队列. public class PaperCalculator { // 用于存 ...
- 浅谈DevExpress<二>:设计一个完整界面(1)
昨天谈了界面的换肤问题,今天拿一个简单的界面来介绍一下怎么设计一个五脏俱全的界面,总体效果如下图(种类的图片随便找的^^):
- 如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展
阅读目录 前言 回顾 本地的一致性 领域事件发布出现异常 订阅者处理出现异常 结语 一.前言 上篇中我们初步运用了领域事件,其中还有一些问题我们没有解决,所以实现是不健壮的,下面先来回顾一下. 二.回 ...
- webview之如何设计一个优雅健壮的Android WebView?(下)(转)
转载:https://iluhcm.com/2018/02/27/design-an-elegant-and-powerful-android-webview-part-two/ (这篇文章写得有点晚 ...
- 如何设计一个异步Web服务——任务调度
接上一篇<如何设计一个异步Web服务——接口部分> Application已经将任务信息发到了Service服务器中,接下来,Service服务器改如何对自身的资源进行合理分配以满足App ...
- WPF 多线程 UI:设计一个异步加载 UI 的容器
对于 WPF 程序,如果你有某一个 UI 控件非常复杂,很有可能会卡住主 UI,给用户软件很卡的感受.但如果此时能有一个加载动画,那么就不会感受到那么卡顿了.UI 的卡住不同于 IO 操作或者密集的 ...
随机推荐
- Python 编码机制
python 编码转换 Python的编码机制,unicode, utf-8, utf-16, GBK, GB2312,ISO-8859-1 等编码之间的转换. 常见的编码转换分为以下几种情况: 自动 ...
- 分析比较多表查询中的IN与JOIN
IN 是子查询的关键字,JOIN 是连接的关键字,项目开发中经常会使用到多表查询,而子查询与连接正是实现多表查询的重要途径.那两者是怎么运行的?IN与JOIN哪个更好?下面就来分析与比较. 现在有te ...
- RequestParam注解的Url参数被省略时该如何处理
RequestParam注解的Url参数被省略时该如何处理 1.RequestParam的用法 ==================== RequestParam注解可以把包含在Url中的参数映射到U ...
- 【CF#338D】GCD Table
[题目描述] 有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j) 读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过 [题解] 要保证g ...
- C# ShowDialog时窗体贱传值得方法
用C#开发应用的时候,通常需要多个窗体!有时候为了打开窗体的时候禁止操作父窗体,我们一般采用模态对话框的方法,也算就是用ShowDialog()方法. 假设有两个窗体A和B,A作为主窗体使用ShowD ...
- JS中的两种刷新方法以及区别和适用范围
在项目中有一个人信息修改的页面,但是修改后显示的却是修改之前的内容,分析问题后发现查询语句写在了修改语句之前,有些某些需要又必须这么写,但是修改信息后先却显示之前的信息也太不科学了. 所以我就想用js ...
- Docker学习笔记_下载镜像更换为国内源,实现快速下载image
1.编辑/etc/docker/daemon.json,增加下面内容: { "registry-mirrors": ["https://registry.docker-c ...
- Eclipse工具
1 ArrayList的常见方法 * a: add(参数) 向集合中添加元素 * b: get(int index) 取出集合中的元素,get方法的参数,写入索引 * c: size() 返回集合的长 ...
- [GO]将随机生成的四位数字拆分后放到一个切片里
package main import ( "math/rand" "time" "fmt" ) func InitData(p *int) ...
- Usage of the @ (at) sign in ASP.NET
from:http://www.mikesdotnetting.com/article/258/usage-of-the-at-sign-in-asp-net Thursday, January 22 ...