winform中很多任务是需要在后台线程(或类似)中完成的,也就是说,经常容易涉及到UI界面与后台工作线程之间的交互。比如UI界面控制后台工作的执行(启动、暂停、停止等),后台工作进度在UI界面上的显示。前两天一个员工在UI线程中访问数据库,刚开始数据库在局域网中,没感觉到什么,后来将数据库移到了外网,发现问题来了,至于问题原因想必诸位都知晓,更详细的解释请参考本系列博客(四)。后将这方面的东西整理了一下,如下:

执行后台任务时,UI界面应该怎么做?大概分两种情况:(我自己随便给取的名字)

(1)一种是模式等待

也就说,后台工作没有完成之前,UI界面不允许操作,如下图:

图1

如上图所示,红色箭头表示后台跟UI界面的交互。

(2)一种是非模式等待

后台工作没完成之前,UI界面可以操作,这个类似文件拷贝出现的信息框,如下图:

图2

如上图所示,红色箭头表示后台与UI界面的交互。

以上是两种情况,以及对应的结构图,我做了一个Demo,包含两种等待窗体,一种即为“模式等待窗体”,另一种为“非模式等待窗体”。源码在文章结束后有下载地址。先来分别看一下两者的代码:

(1)模式等待窗体

 public partial class frmWait : Form
{
bool _run = true;
public frmWait()
{
InitializeComponent();
}
public object DoWait(object param)
{
List<string> list = new List<string>();
int count = (int)param;
progressBar1.Maximum = count; //---------------------以下代码片段可以使用线程代替
((Action)delegate()
{
System.Threading.Thread.Sleep(); for (int i = ; i < count; ++i) //耗时操作
{
if (_run)
{
string s = DateTime.Now.ToLongTimeString();
list.Add(s);
this.Invoke((Action)delegate()
{
if (!IsDisposed)
{
progressBar1.Value = i;
label1.Text = "正在载入字符串 \"" + s + "\"";
}
});
System.Threading.Thread.Sleep();
}
else
{
break;
}
} }).BeginInvoke(new AsyncCallback(OnAsync), null); //异步执行后台工作
//------------------------ ShowDialog(); //UI界面等待
return list; //后台工作执行完毕 可以使用结果
}
private void OnAsync(IAsyncResult ar)
{
if (_run) //后台工作正常结束
DialogResult = DialogResult.OK;
}
private void frmWait_Load(object sender, EventArgs e)
{ } private void button1_Click(object sender, EventArgs e)
{
_run = false; //UI界面控制后台结束
DialogResult = DialogResult.Cancel;
}
}

如上代码所示,后台任务很简单,就是返回指定数目(param)个字符串,存放在一个list中,使用frmWait也很简单:

  using (frmWait frmw = new frmWait())
{
List<string> list = frmw.DoWait() as List<string>; //弹出模式等待窗体 实时更新显示后台工作进度 后台工作结束后 等待窗体消失 UI线程继续执行...
MessageBox.Show("加载字符串 " + list.Count + "个");
}

(2)非模式等待窗体

  public partial class frmNoWait : Form
{
bool _run = true;
public frmNoWait()
{
InitializeComponent();
}
private void OnAsync(IAsyncResult ar)
{
// ar.AsyncState as List<string> 后台工作执行完毕的结果 if (_run) //后台工作正常结束
this.Invoke((Action)delegate()
{
Close();
});
}
public void DoNoWait(int param)
{
List<string> list = new List<string>();
int count = (int)param;
progressBar1.Maximum = count; //-----------------------以下代码片段 可以使用线程代替
((Action)delegate()
{
try
{
System.Threading.Thread.Sleep();
for (int i = ; i < count; ++i) //耗时操作
{
if (_run)
{
string s = DateTime.Now.ToLongTimeString();
list.Add(s);
this.Invoke((Action)delegate()
{
if (!IsDisposed)
{
progressBar1.Value = i;
label1.Text = "正在载入字符串 \"" + s + "\"";
}
});
System.Threading.Thread.Sleep();
}
else
{
break;
}
}
}
catch
{ }
}).BeginInvoke(new AsyncCallback(OnAsync), list); //异步执行后台工作
//---------------------------- Show();//UI界面不用等待
}
private void frmNoWait_Load(object sender, EventArgs e)
{
Text += (" " + Form1.index++ + "号");
} private void button1_Click(object sender, EventArgs e)
{
Close();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
_run = false; //UI界面控制后台结束
}
}

如上代码所示,后台工作开始后,弹出一个非模式对话框,UI界面可以继续操作,也就是说,你可以出现多个frmNoWait窗体,使用很简单,如下:

 frmNoWait frmnw = new frmNoWait();
frmnw.DoNoWait(); //弹出窗体
//UI界面继续...

至于怎么通知UI界面,后台工作结束了,你可以在OnAsync中完成这个功能。

最后上几张截图:

图3

图4

源码下载地址:http://files.cnblogs.com/xiaozhi_5638/ProgressForm.rar

希望有帮助!

.net开发笔记(十八) winform中的等待框的更多相关文章

  1. python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置

    python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...

  2. 漫谈程序员(十八)windows中的命令subst

    漫谈程序员(十八)windows中的命令subst 用法格式 一.subst [盘符] [路径]  将指定的路径替代盘符,该路径将作为驱动器使用 二.subst /d 解除替代 三.不加任何参数键入  ...

  3. Java开发笔记(八十九)缓存字节I/O流

    文件输出流FileOutputStream跟FileWriter同样有个毛病,每次调用write方法都会直接写到磁盘,使得频繁的写操作性能极其低下.正如FileWriter搭上了缓存兄弟Buffere ...

  4. Java开发笔记(八十八)文件字节I/O流

    前面介绍了如何使用字符流读写文件,并指出字符流工具的处理局限,进而给出随机文件工具加以改进.随机文件工具除了支持访问文件内部的任意位置,更关键的一点是通过字节数组读写文件数据,采取字节方式比起字符方式 ...

  5. Java开发笔记(八十六)通过缓冲区读写文件

    前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...

  6. Java开发笔记(八十五)通过字符流读写文件

    前面介绍了文件的信息获取.管理操作,以及目录下的文件遍历,那么文件内部数据又是怎样读写的呢?这正是本文所要阐述的内容.File工具固然强大,但它并不能直接读写文件,而要借助于其它工具方能开展读写操作. ...

  7. Java开发笔记(八十四)文件与目录的管理

    程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘.固定在机箱中的硬盘.插在光驱中的光盘.插在USB接口上的U盘 ...

  8. Java开发笔记(八十二)注解的基本单元——元注解

    Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...

  9. Android UI开发第二十八篇——Fragment中使用左右滑动菜单

    Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...

随机推荐

  1. 传统B2B中小型企业如何做好全网营销

    优网特独创全网营销服务理念,全网营销即以企业网站推广为核心,通过SEO.SEM.BBS营销.博客营销.微营销.即时通讯营销.网络口碑营销.视频营销.邮件营销.SNS营销等网络营销手段,全面提升企业网站 ...

  2. 123. Best Time to Buy and Sell Stock (三) leetcode解题笔记

    123. Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the pric ...

  3. MySQL数据库安装与配置详解

    转载提示:在原文http://www.cnblogs.com/sshoub/p/4321640.html基础上修改. 目录 一.概述 二.MySQL安装 三.安装成功验证 四.NavicatforMy ...

  4. 也说说angularJs里的evalAsync

    虽说angular都快出2.0了,到了2.0这些东东都会被干掉.不过我们眼前的事还是要处理. $evalAsync和$timeout到底什么区别,网上说法很多,最近看到的是说在directive里就怎 ...

  5. php压缩文件

    $filename = './qrcode.zip'; // 最终生成的文件名(含路径) //生成文件 $zip = new ZipArchive (); // 使用本类,linux需开启zlib,w ...

  6. where和having子句的区别

    having子句可以让我们筛选成组后的各种数据,having子句在查询过程中慢于聚合语句 having的用法 having子句可以让我们筛选成组后的各种数据,having子句在查询过程中慢于聚合语句( ...

  7. MATLAB-octave中向量场图的可视化

    参考http://379910987.blog.163.com/blog/static/33523797201162223310546/ 设二维函数z=f(x,y),其中z为海拔,x为东西测向距离而y ...

  8. 【算法与数据结构】二叉搜索树的Java实现

    为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指 ...

  9. easyconf——基于AugularJS的配置管理系统开发框架

    目录 1 easyconf的诞生2 easyconf的设计理念 2.1 总体设计 2.2 细节设计 2.2.1 CRUD操作 2.2.2 即时校验 2.2.3 下拉框设计3 easyconf使用指南 ...

  10. Ubuntu下不重装系统安装SSD总结

    一.要想给自己的机子装个固态,但又不想重装系统,各种配置,那么就要先把自己的系统从HDD复制到SSD上,这里说下我的情况.我的HDD 是500G ubuntu系统,安装的时候没有分区,默认是dev/s ...