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

      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

希望有帮助!

转载于:https://my.oschina.net/newsherlock/blog/425414

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
与前版功能基本相似,修正了部分bug,对界面进行了美化,目前这个美化相信应该够用了,因为时间问题没有增加可自定义界面功能,等有时间再提供吧,压缩文件使用“好压”做的,里面有一个例子,图片资源编辑工具,大家可以测试一下效果,里面也有详细说明,图片资源编辑器大家也可以用到自己的程序,方便程序的图片统一管理和调用,菜鸟,达人们别笑话我了。 这里还是在说一下等待窗体的具体使用方法吧 首先将LOADing.dll,DevComponents.DotNetBar2.dll两个dll文件复制到你程序目录,在程序项目引用LOADing.dll,在要使用的地方 //先实例 LOADing.FORMshow FRload = new LOADing.FORMshow(); //再调用showto方法,其的参数this为你调用等待窗体的主窗体对象,delegate { }为委托,IMGclass_AddFlie_r()为功能处理函数,其所传递的参数第一的FRload必须为固定的创建等待窗体的实例对象,后面跟所需要传递的对象参数。 FRload.showto(this, delegate { IMGclass_AddFlie_r(new object[] { FRload, iclass, fileDialog1.FileNames, _at.SelectedNode.Text }); },true); //这个为数据处理部分 private void IMGclass_AddFlie_r(object[] d) { for (int i = 0; i <= ((string[])d[2]).Length - 1; i++) { ((IMGclass)d[1]).top[d[3].ToString()].Add("标" + ((IMGclass)d[1]).top[d[3].ToString()].Count, BinToCmd(((string[])d[2])[i])); f_new_hand(new object[] { ((IMGclass)d[1]).top[d[3].ToString()], "标" + (((IMGclass)d[1]).top[d[3].ToString()].Count - 1) }); ((LOADing.FORMshow)d[0]).send("加载图片文件:", Convert.ToInt32((Convert.ToSingle(i) / (Convert.ToSingle(((string[])d[2]).Length) / Convert.ToSingle(100))))); } BinToclass(((IMGclass)d[1]), _path[_at.SelectedNode.Parent.Text]); } 好了,使用起来很简单,看看上面的例子就会了,如需索要源码或者要提问的话,请联系QQ76230454.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值