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's eleventh day for me
python2 中没有nonlocal. 函数名是什么? 函数名就是函数的名字, 本质:变量,特殊的变量. 1.单独打印函数名: def func(): print(666) print(func) ...
- VC6编写的Dll调试方法
Dll工程运行时指定调用exe程序. 关键!!往往被忽略:exe中也一定要指向此调用dll,如果指向不对,什么效果也没有!
- MFC 控件使用汇总
一.动态创建button CButton *button=new CButton; button->Create(_T(,,,),);//最后一个是ID BEGIN_MESSAGE_MAP(CM ...
- Python中常见的异常处理
异常和错误 part1:程序中难免出现错误,而错误分成两种 1. 语法错误(这种错误,根本过不了Python解释器的语法检测,必须在程序执行前就改正) # 语法错误示范一 if # 语法错误示范二 d ...
- Windows + Ubuntu 双系统安装
前言:本篇文章是对之前文章的更新,更新的主内容是把原来用手机拍摄的图片换成了虚拟机的截图,以及对磁盘划分的新的见解和一些使用感受,原本是打算删除之前的那篇Win + Ubuntu双系统的文章的,后来想 ...
- webpack4+vue2+axios+vue-router的多页+单页混合应用框架
VUE2的单页应用框架有人分享了,多页应用框架也有人分享了,这里就分享一个单页和多页的混合应用框架吧,初现雏形,还有很多需要优化和改善的地方... 结尾有github地址. 项目结构 │ ├─buil ...
- The centos disc was not found in any of your drives.Please insert the centos disc and press OK to retry
查看虚拟机设置中关于CDROM的选项,将CDROM的状态改为已连接,不要奇怪,勾选上之后再按下OK就好了
- node.js开发指南读书笔记(1)
3.1 开始使用Node.js编程 3.1.1 Hello World 将以下源代码保存到helloworld.js文件中 console.log('Hello World!'); console.l ...
- C程序栈内存堆内存的地址
#include <stdio.h> #include <malloc.h> int main() { char * p1, * p2; p1=(char *)malloc(2 ...
- 安装sshpass:No package sshpass available
安装sshpass的时候,报了如下错误: No Package sshpass available 更改软件源之后也无效.直到看到StackOverFlow上的一个问题:https://stackov ...