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中的等待框的更多相关文章
-
python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置
python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...
-
漫谈程序员(十八)windows中的命令subst
漫谈程序员(十八)windows中的命令subst 用法格式 一.subst [盘符] [路径] 将指定的路径替代盘符,该路径将作为驱动器使用 二.subst /d 解除替代 三.不加任何参数键入 ...
-
Java开发笔记(八十九)缓存字节I/O流
文件输出流FileOutputStream跟FileWriter同样有个毛病,每次调用write方法都会直接写到磁盘,使得频繁的写操作性能极其低下.正如FileWriter搭上了缓存兄弟Buffere ...
-
Java开发笔记(八十八)文件字节I/O流
前面介绍了如何使用字符流读写文件,并指出字符流工具的处理局限,进而给出随机文件工具加以改进.随机文件工具除了支持访问文件内部的任意位置,更关键的一点是通过字节数组读写文件数据,采取字节方式比起字符方式 ...
-
Java开发笔记(八十六)通过缓冲区读写文件
前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...
-
Java开发笔记(八十五)通过字符流读写文件
前面介绍了文件的信息获取.管理操作,以及目录下的文件遍历,那么文件内部数据又是怎样读写的呢?这正是本文所要阐述的内容.File工具固然强大,但它并不能直接读写文件,而要借助于其它工具方能开展读写操作. ...
-
Java开发笔记(八十四)文件与目录的管理
程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘.固定在机箱中的硬盘.插在光驱中的光盘.插在USB接口上的U盘 ...
-
Java开发笔记(八十二)注解的基本单元——元注解
Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...
-
Android UI开发第二十八篇——Fragment中使用左右滑动菜单
Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...
随机推荐
-
[LeetCode] Mini Parser 迷你解析器
Given a nested list of integers represented as a string, implement a parser to deserialize it. Each ...
-
Hadoop HDFS负载均衡
Hadoop HDFS负载均衡 转载请注明出处:http://www.cnblogs.com/BYRans/ Hadoop HDFS Hadoop 分布式文件系统(Hadoop Distributed ...
-
ubuntu安装cacti错误
安装cacti时,明明mysql信息都配置正确了,权限也分配好了,可是仍然报错,如下: 这时可以试试到/etc/cacti目录下,修改debian.php中的mysql配置信息,问题应该就能解决了.
-
hadoop中NameNode、DataNode和Client三者之间协作关系及通信方式介绍
<ignore_js_op> 1)NameNode.DataNode和Client NameNode可以看作是分布式文件系统中的管理者,主要负责管理文件系统的命名空间.集群 ...
-
IOS应用开发版本控制工具之Versions使用
Versions版本控制工具破解版(Versions.zip)下载请见本博文附件.下载后在MAC安装完以后,图标是莲花状.见下图: 双击运行如下图: 点击Repository,连接SVN服务器R ...
-
python项目
python实战项目: http://www.the5fire.com/category/python实战/ python基础教程中的十个项目: python项目练习一:即时标记 python项目练习 ...
-
c# in deep 之Lambda表达式于LINQ表达式结合后令人惊叹的简洁(2)
当Lambda表达式和LINQ一起使用时,我们会发现原本冗长的代码会变得如此简单.比如我们要打印0-10之间的奇数,让其从高到低排列并求其平方根,现在只用一行代码即可完成其集合的生成,直接上代码: v ...
-
如何生成git ssh key
公司有自己的git版本控制,自己注册账号后,管理员同意,就可以查看项目代码了,但是要克隆的话需要在本地生成git ssh key 一.进入.ssh文件夹. cd ~/.ssh 若没有.ssh文件夹,则 ...
-
hihoCoder week15 最近公共祖先&#183;二
tarjan求lca 就是dfs序中用并查集维护下,当访问到询问的第二个点u的时候 lca就是第一点的find(fa[v]) fa[v] = u; // 当v为u的儿子 且 v已经dfs完毕 #i ...
-
pytorch人脸识别——自己制作数据集
这是一篇面向新手的博文:因为本人也是新手,记录一下自己在做这个项目遇到的大大小小的坑. 按照下面的例子写就好了 import torch as t from torch.utils import da ...