打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
.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                         else36                         {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 }

如上代码所示,后台任务很简单,就是返回指定数目(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             }

(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                 try28                 {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                         else47                         {48                             break;49                         }50                     }51                 }52                 catch53                 {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     }

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

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

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

最后上几张截图:

图3

图4

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

希望有帮助!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# this.Invoke()的作用与用法
用C#写一个简单的Login窗口
ASP.NET无刷新二级联动下拉列表,同样适与firefox
C#多线程UI界面处理
详解在数据查看界面中增加记录导航功能,你应该需要的
Asp.net 后台添加CSS、JS、Meta标签
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服