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 操作或者密集的 ...
随机推荐
- 使用Kismet进行网络扫描
执行命令启动Kismet root@sch01ar:~# kismet 这个界面是用来设置颜色的,单击Yes按钮,默认颜色灰色 这个界面显示正在使用root用户运行Kismet工具,单击OK 这个界面 ...
- 不用jquery实现tab页切换,刷新,后退,前进状态自动维护 很好用
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Android独立交叉编译环境搭建
我们经常需将一些C/C++源码编译成本地二进制,直接在android的linux内核上运行,这是就需要进行交叉编译.由于Android的运行环境核普通Linux又区别,所以常规方式针对ARM进行交叉编 ...
- C51串口的SCON寄存器及工作…
原文地址:C51串口的SCON寄存器及工作方式作者:batistar 一,串行口控制寄存器SCON 它用于定义串行口的工作方式及实施接收和发送控制.字节地址为98H,其各位定义如下表: D7 D6 D ...
- Xcode迁移工程常见问题
[Xcode迁移工程常见问题] 1.Header Search Paths (HEADER_SEARCH_PATHS) 是否设置正确.在Search Paths group下. 2.Framework ...
- ionic中的后退方法
1)$ionicHistory.goBack(); 2)$ionicNavBarDelegate.back(); 个人感觉: 1)$ionicHistory.goBack()会按照html历史来后退 ...
- inux php pdo mysql 扩展
今天在本机部署了一个pdo项目,发现一些问题,真没想到pdo mysql,不容易装啊,哈哈,我说的不容易,是因为php5.3以前版本,yum源里面根本没有.部署后就报,Undefined class ...
- caret 分类回归树 用法
http://topepo.github.io/caret/feature-selection-overview.html
- jq获取table总行数
var rows = $('table').find("tr").length;
- Python中常用模块二
一.hashlib (加密) hashlib:提供摘要算法的模块 1.正常的md5算法 import hashlib # 提供摘要算法的模块 md5 = hashlib.md5() md5.upd ...