.net开发笔记(十八) winform中的等待框
.net开发笔记(十八) winform中的等待框
IT周见智 发表于3年前
.net开发笔记(十八) winform中的等待框
  • 发表于 3年前
  • 阅读 10
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

      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周见智
粉丝 10
博文 61
码字总数 185891
×
IT周见智
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: