文档章节

.net开发笔记(十八) winform中的等待框

IT周见智
 IT周见智
发布于 2015/06/05 17:17
字数 1156
阅读 13
收藏 0

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

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

(1)一种是模式等待

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

图1

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

(2)一种是非模式等待

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

图2

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

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

(1)模式等待窗体

 1 public partial class frmWait : Form
 2     {
 3         bool _run = true;
 4         public frmWait()
 5         {
 6             InitializeComponent();
 7         }
 8         public object DoWait(object param)
 9         {
10             List<string> list = new List<string>();
11             int count = (int)param;
12             progressBar1.Maximum = count;
13 
14             //---------------------以下代码片段可以使用线程代替
15             ((Action)delegate()
16             {
17                 System.Threading.Thread.Sleep(1000);
18 
19                     for (int i = 0; i < count; ++i) //耗时操作
20                     {
21                         if (_run)
22                         {
23                             string s = DateTime.Now.ToLongTimeString();
24                             list.Add(s);
25                             this.Invoke((Action)delegate()
26                             {
27                                 if (!IsDisposed)
28                                 {
29                                     progressBar1.Value = i;
30                                     label1.Text = "正在载入字符串 \"" + s + "\"";
31                                 }
32                             });
33                             System.Threading.Thread.Sleep(500);
34                         }
35                         else
36                         {
37                             break;
38                         }
39                     }
40 
41             }).BeginInvoke(new AsyncCallback(OnAsync), null);  //异步执行后台工作
42             //------------------------
43 
44             ShowDialog(); //UI界面等待
45             return list; //后台工作执行完毕 可以使用结果
46         }
47         private void OnAsync(IAsyncResult ar)
48         {
49             if (_run) //后台工作正常结束
50                 DialogResult = DialogResult.OK;
51         }
52         private void frmWait_Load(object sender, EventArgs e)
53         {
54 
55         }
56 
57         private void button1_Click(object sender, EventArgs e)
58         {
59             _run = false; //UI界面控制后台结束
60             DialogResult = DialogResult.Cancel;
61         }
62 }
View Code

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

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

(2)非模式等待窗体

 1  public partial class frmNoWait : Form
 2     {
 3         bool _run = true;
 4         public frmNoWait()
 5         {
 6             InitializeComponent();
 7         }
 8         private void OnAsync(IAsyncResult ar)
 9         {
10             // ar.AsyncState as List<string> 后台工作执行完毕的结果
11 
12             if (_run) //后台工作正常结束
13                 this.Invoke((Action)delegate()
14                 {
15                     Close();
16                 });
17         }
18         public void DoNoWait(int param)
19         {
20             List<string> list = new List<string>();
21             int count = (int)param;
22             progressBar1.Maximum = count;
23 
24             //-----------------------以下代码片段 可以使用线程代替
25             ((Action)delegate()
26             {
27                 try
28                 {
29                     System.Threading.Thread.Sleep(1000);
30                     for (int i = 0; i < count; ++i) //耗时操作
31                     {
32                         if (_run)
33                         {
34                             string s = DateTime.Now.ToLongTimeString();
35                             list.Add(s);
36                             this.Invoke((Action)delegate()
37                             {
38                                 if (!IsDisposed)
39                                 {
40                                     progressBar1.Value = i;
41                                     label1.Text = "正在载入字符串 \"" + s + "\"";
42                                 }
43                             });
44                             System.Threading.Thread.Sleep(500);
45                         }
46                         else
47                         {
48                             break;
49                         }
50                     }
51                 }
52                 catch
53                 {
54 
55                 }
56             }).BeginInvoke(new AsyncCallback(OnAsync), list); //异步执行后台工作
57             //----------------------------
58 
59             Show();//UI界面不用等待
60         }
61         private void frmNoWait_Load(object sender, EventArgs e)
62         {
63             Text += (" " + Form1.index++ + "");
64         }
65 
66         private void button1_Click(object sender, EventArgs e)
67         {
68             Close();
69         }
70         protected override void OnFormClosing(FormClosingEventArgs e)
71         {
72             base.OnFormClosing(e);
73             _run = false; //UI界面控制后台结束
74         }
75     }
View Code

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

1 frmNoWait frmnw = new frmNoWait();
2 frmnw.DoNoWait(50);   //弹出窗体
3 //UI界面继续...
View Code

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

最后上几张截图:

图3

图4

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

希望有帮助!

© 著作权归作者所有

共有 人打赏支持
IT周见智

IT周见智

粉丝 10
博文 61
码字总数 185891
作品 0
西青
我的友情链接

51CTO博客开发 吴光科-京峰Linux运维培训 上山路十八弯 pc的个人博客 不安分与好奇心 Linux运维之路启示录 抚琴煮酒 MJ为的笔记和总结 毛毛鸭 chinanet 煮酒品茶 柠檬 Linux运维重难点学习笔...

运维猫
2017/11/22
0
0
《Linux内核设计与实现》读书笔记 - 目录 (完结)

《Linux内核设计与实现》读书笔记 - 目录 (完结) 读完这本书回过头才发现, 第一篇笔记居然是 2012年8月发的, 将近一年半的时间才看完这本书(汗!!!). 为了方便以后查看, 做个《Linux内核设计...

你的猫大哥
01/14
0
0
关于安卓应用迁移至Windows 8应用概览

开源力量公开课第二十八期-安卓应用迁移至Windows应用概览 2013年08月27日 ⁄ 公开课 ⁄ 评论关闭

刘华1314520
2013/08/21
143
0
如何在MyBatis-3.2.7中使用Log4j2 rc2——MyBatis学习笔记之十九

前天我上传了我的MyBatis系列课程(http://edu.51cto.com/course/course_id-1110.html)的第六讲,主要内容是如何使用Log4j2(具体版本为v2.0-rc1)为MyBatis 3.2.7配置日志。实际上目前最新...

NashMaster2011
2014/07/09
0
0
在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口

在我很早的WInform随笔《WinForm界面开发之"SplashScreen控件"》有介绍如何使用闪屏的处理操作,不过那种是普通WInform和DevExpress都适用的方案,如果是基于DevExpress,那么可以使用更简便...

walb呀
2017/12/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

一次由HandlerInterceptor进行的深入思考

HandlerInterceptor 是SpringFramework为我们提供的拦截器,一般我们可以用来鉴权或者日志记录等。 它是一个interface,主要方法有: /** * Intercept the execution of a handler. Called...

kipeng300
31分钟前
1
0
cmd中查询mysql表出现中文乱码

问题:在pycharm中正常的fetchall拉取数据,能够正常显示,而在cmd中直接select却出现中文乱码。 解决思路:右键查看cmd命令窗口属性得到,cmd窗口默认编码是gbk(如下图所示),而设置的mys...

fang_faye
57分钟前
2
0
centOS 安装Python3与python2并存

centOS 安装Python3与python2并存 如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!!!! 不要动现有的python2环...

MedivhXu
今天
2
0
Spring JdbcTemplate模板模式与回调结合分析

在看Spring的JdbcTemplate的时候,看到其将模板模式和回调模式结合使用的实现,可以精妙的解决很多的问题。详见Spring中涉及的设计模式总结中的关于模板模式和回调模式结合的具分析,本文利用...

宸明
今天
1
0
docker update:更新一个或多个容器的配置

更新容器的配置 docker update:更新一个或多个容器的配置。 具体内容请访问:https://docs.docker.com/engine/reference/commandline/update/#options 语法:docker update [OPTIONS] CONTA...

lwenhao
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部