在winform中测试时主要遇到的问题是跨线程调用控件与如何让调用时间短的异步方法等待主线程的调用完成。在后者中又遇到messagebox使界面死亡的问题。

  第一个问题通过新建委托,通过委托的BeginInvoke方法调用方法来对控件进行操作。第二个问题最后通过取消原来的异步方法将其放在主线程上,而将原来主线程上执行时间较长的方法改为异步调用。之所以采用这种方法的原因是因为在使用WaitOne方法的时候在遇到messagebox的时候会使界面死亡,所有线程卡死,虽然可以在异步方法或者回调方法中显示messagebox但是由于在主线程完成时只能使用set方法通知异步线程主线程已经完成,无法传入其他参数使异步方法根据参数显示不同的messagebox(可能我不知道),导致无法满足项目要求。

 

 在主线程的方法中创建异步委托并启动异步方法。

代码
1 this.uCwaiting1.Visible = true;
2 Application.DoEvents();
3         //异步委托
4 XjzxAsyncDelegate dlgt = new XjzxAsyncDelegate(saveData);
5         //开始异步调用
6         //xe,xmes,yskmx,fkmms均为异步方法所需要的参数
7 IAsyncResult ar = dlgt.BeginInvoke(xe, xmes, yskmx, fkmms, new AsyncCallback(saveCallback), dlgt);

 

 异步方法:

代码
1 //异步方法
2 void saveData(XsxxEntity xe, XsmxxxEntity[] xmes, YsOrYfEntity yskmx, FkmxEntity[] fkmms)
3 {
4 //数据库操作(需要较长时间)
5 ArgsHelp ah = xsgl.xjzxOperation(xe, xmes, yskmx, fkmms);
6 //在异步方法中使用messagebox
7 if (ah.flag) MessageBox.Show("操作成功");
8 else MessageBox.Show("操作失败!" + ah.msg);
9 }

 

 

 

异步回调方法(用来跨线程调用控件)

1 private void saveCallback(IAsyncResult ar)
2 {
3 BackgroundHandler bg = new BackgroundHandler(unshow);
4 this.BeginInvoke(bg);
5 }

 

对控件进行操作的方法

1 void unshow()
2 {
3 uCwaiting1.Visible = false;
4 this.Close();
5 }

 

 

 

 

 在测试时使用的代码

 

代码
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Threading;
10
11 namespace 跨线程调用控件
12 {
13 public partial class Form1 : Form
14 {
15
16 double j = 0;
17 AsyncDelegate dlgt;
18 IAsyncResult ar;
19 public Form1()
20 {
21 InitializeComponent();
22 }
23
24 private void label1_Click(object sender, EventArgs e)
25 {
26 dlgt = new AsyncDelegate(crossThread);
27 ar = dlgt.BeginInvoke(new AsyncCallback(callbackMethod), dlgt);
28
29 }
30
31 void doit(int i)
32 {
33 j = 0;
34 progressBar1.Value = 0;
35 progressBar1.Visible = true;
36 do
37 {
38 j = j + 1;
39 progressBar1.Increment(i);
40 } while (j != 100);
41 }
42
43 void crossThread()
44 {
45 ProgressBarHandler pbDlgt = new ProgressBarHandler(doit);
46 this.Invoke(pbDlgt,1);
47 }
48
49 void runBackground()
50 {
51 ButtonHandler buttonDlgt = new ButtonHandler(userControl12.showThis);
52 this.BeginInvoke(buttonDlgt);
53 }
54
55 void callbackMethod(IAsyncResult ar)
56 {
57 //AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState;
58 //dlgt.EndInvoke(ar);
59 ButtonHandler buttonDlgt = new ButtonHandler(unShow);
60 this.BeginInvoke(buttonDlgt);
61 }
62
63 void unShow()
64 {
65 DialogResult dr=
66 MessageBox.Show("图标即将消失!","提示",MessageBoxButtons.OKCancel);
67 if (dr == DialogResult.OK)
68 {
69 userControl12.Visible = false;
70 this.Close();
71 }
72 else
73 {
74 return;
75 }
76 }
77
78 }
79 }
80

运行结果

form2作为MDI主窗体,用来测试在异步回调方法中使用this.Close()是否会关闭整个窗体。

progressbar在增加的同时窗体上的图标也在变化,说明异步线程的运行并没有影响主线程,而且两者在同意时间片上运行