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

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

(1)一种是模式等待

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

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

图1

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

(2)一种是非模式等待

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

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

图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

相关文章: