一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了。稍后我会上传我的代码,包含测试程序以及之前两边博文谈到的控件,这里我还实现了一个类似雷达扫描的等待窗体,大家可以稍后查看。
实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问UI界面。为了方便调用,我在这里写了一个静态的子线程窗体管理类DialogWindowsManager。
1.遮挡主窗体
大家都知道,showDialog方法就是最好的遮挡效果,但是由于它是线程阻塞的,因此每当我们想到这里的时候会有一个误区,认为调用showDialog一定会阻塞前台界面,其实这里的阻塞只是阻塞调用方法所在的线程,并不是一定会阻塞主线程,因此在子线程中调用showDialog方法即可达到效果。实际测试时发现遮挡效果确实有了,可惜每次showDialog的时候窗体会满屏幕乱飞,好吧,最好的方法当然是设置onwer,不过我一直没尝试成功,因为主窗体与子窗体一直处于两个线程中,最后我通过一个算法将位置计算出来之后赋值给了子窗体。代码如下:
1 /// <summary> 2 /// 打开等待窗体线程 3 /// </summary> 4 public static void ShowWaitingForm(Window onwer) { 5 double[] d = new double[2]; 6 d[0] = onwer.Top + onwer.Height / 2 - 50; 7 d[1] = onwer.Left + onwer.Width / 2 - 50; 8 if (WaitingFormThread == null) 9 { 10 WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm)); 11 WaitingFormThread.SetApartmentState(ApartmentState.STA); 12 WaitingFormThread.Start(d); 13 } 14 else { 15 CloseWaitingForm(); 16 ShowWaitingForm(onwer); 17 } 18 }
2.跨线程访问
这里不得不说WPF还是很给力的,因为它提供了Dispatcher来获取当前要更新的线程,这里网上资料很多,我就不多做解释了,直接上代码:
1 /// <summary> 2 /// 设置进度条百分比 3 /// </summary> 4 /// <param name="d">百分比</param> 5 public static void setProgrssFormPercent(double d) { 6 if (cf != null) { 7 cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } })); 8 Thread.Sleep(50); 9 } 10 }
3.注意事项
子线程也是UI线程,因此线程一定要设置为ApartmentState.STA状态。
完成的线程管理代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Windows; 7 8 namespace MyUserControlLibrary 9 { 10 public static class DialogWindowsManager 11 { 12 #region 属性 13 14 /// <summary> 15 /// 等待窗体处理线程 16 /// </summary> 17 static Thread WaitingFormThread; 18 /// <summary> 19 /// 进度条进程 20 /// </summary> 21 static Thread CircleProgressFormThread; 22 23 /// <summary> 24 /// 等待进度条进程 25 /// </summary> 26 static Thread WaitingAndProgressFormThread; 27 28 /// <summary> 29 /// 进度条窗体 30 /// </summary> 31 static CircleProgressForm cf; 32 /// <summary> 33 /// 等待进度条 34 /// </summary> 35 static WaitingAndProgressForm wpf; 36 #endregion 37 38 #region 私有方法 39 40 /// <summary> 41 /// 打开等待窗体方法 42 /// </summary> 43 private static void showWaitingForm(object o) 44 { 45 double[] d = (double[])o; 46 WaitingForm wf = new WaitingForm(); 47 wf.WindowStartupLocation = WindowStartupLocation.Manual; 48 wf.Top = d[0]; 49 wf.Left = d[1]; 50 wf.ShowDialog(); 51 } 52 53 /// <summary> 54 /// 打开进度条窗体方法 55 /// </summary> 56 /// <param name="o">显示位置集合 double[] 0-Top 1-Left</param> 57 private static void showCircleProgressForm(object o) 58 { 59 double[] d = (double[])o; 60 cf = new CircleProgressForm(); 61 cf.WindowStartupLocation = WindowStartupLocation.Manual; 62 cf.Top = d[0]; 63 cf.Left = d[1]; 64 cf.ShowDialog(); 65 } 66 67 /// <summary> 68 /// 打开进度条窗体方法 69 /// </summary> 70 /// <param name="o">显示位置集合 double[] 0-Top 1-Left</param> 71 private static void showWaitingAndProgressForm(object o) 72 { 73 object[] m = (object[])o; 74 double[] d = (double[])m[0]; 75 wpf = new WaitingAndProgressForm(); 76 wpf.MainControl.ShowType = (WaitAndProgressType)m[1]; 77 wpf.WindowStartupLocation = WindowStartupLocation.Manual; 78 wpf.Top = d[0]; 79 wpf.Left = d[1]; 80 wpf.ShowDialog(); 81 } 82 83 #endregion 84 85 #region 公有方法 86 87 /// <summary> 88 /// 打开等待窗体线程 89 /// </summary> 90 public static void ShowWaitingForm(Window onwer) { 91 double[] d = new double[2]; 92 d[0] = onwer.Top + onwer.Height / 2 - 50; 93 d[1] = onwer.Left + onwer.Width / 2 - 50; 94 if (WaitingFormThread == null) 95 { 96 WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm)); 97 WaitingFormThread.SetApartmentState(ApartmentState.STA); 98 WaitingFormThread.Start(d); 99 } 100 else { 101 CloseWaitingForm(); 102 ShowWaitingForm(onwer); 103 } 104 } 105 106 /// <summary> 107 /// 关闭等待窗体线程 108 /// </summary> 109 public static void CloseWaitingForm() 110 { 111 WaitingFormThread.Abort(); 112 WaitingFormThread.Join(); 113 WaitingFormThread.DisableComObjectEagerCleanup(); 114 WaitingFormThread = null; 115 } 116 117 /// <summary> 118 /// 打开进度条窗体线程 119 /// </summary> 120 public static void ShowCircleProgressForm(Window onwer) 121 { 122 double[] d = new double[2]; 123 d[0] = onwer.Top + onwer.Height / 2 - 50; 124 d[1] = onwer.Left + onwer.Width / 2 - 50; 125 if (CircleProgressFormThread == null) 126 { 127 CircleProgressFormThread = new Thread(new ParameterizedThreadStart(showCircleProgressForm)); 128 CircleProgressFormThread.SetApartmentState(ApartmentState.STA); 129 CircleProgressFormThread.Start(d); 130 Thread.Sleep(100); 131 } 132 else 133 { 134 CloseCircleProgressForm(); 135 ShowCircleProgressForm(onwer); 136 } 137 } 138 139 /// <summary> 140 /// 设置进度条百分比 141 /// </summary> 142 /// <param name="d">百分比</param> 143 public static void setProgrssFormPercent(double d) { 144 if (cf != null) { 145 cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } })); 146 Thread.Sleep(50); 147 } 148 } 149 150 /// <summary> 151 /// 关闭进度条窗体线程 152 /// </summary> 153 public static void CloseCircleProgressForm() 154 { 155 CircleProgressFormThread.Abort(); 156 CircleProgressFormThread.Join(); 157 CircleProgressFormThread.DisableComObjectEagerCleanup(); 158 CircleProgressFormThread = null; 159 cf = null; 160 } 161 162 /// <summary> 163 /// 打开等待进度条窗体线程 164 /// </summary> 165 public static void ShowWaitingAndProgressForm(Window onwer,WaitAndProgressType t) 166 { 167 object[] o = new object[2]; 168 double[] d = new double[2]; 169 d[0] = onwer.Top + onwer.Height / 2 - 50; 170 d[1] = onwer.Left + onwer.Width / 2 - 50; 171 o[0] = d; 172 o[1] = t; 173 if (WaitingAndProgressFormThread == null) 174 { 175 WaitingAndProgressFormThread = new Thread(new ParameterizedThreadStart(showWaitingAndProgressForm)); 176 WaitingAndProgressFormThread.SetApartmentState(ApartmentState.STA); 177 WaitingAndProgressFormThread.Start(o); 178 Thread.Sleep(100); 179 } 180 else 181 { 182 CloseWaitingAndProgressForm(); 183 ShowWaitingAndProgressForm(onwer,t); 184 } 185 } 186 187 /// <summary> 188 /// 设置进度条百分比 189 /// </summary> 190 /// <param name="d">百分比</param> 191 public static void setWaitingAndProgressFormPercent(double d) 192 { 193 if (wpf != null) 194 { 195 wpf.Dispatcher.BeginInvoke(new Action(() => { if (wpf != null) { wpf.setPercent(d); } })); 196 Thread.Sleep(50); 197 } 198 } 199 200 /// <summary> 201 /// 关闭等待进度条窗体线程 202 /// </summary> 203 public static void CloseWaitingAndProgressForm() 204 { 205 WaitingAndProgressFormThread.Abort(); 206 WaitingAndProgressFormThread.Join(); 207 WaitingAndProgressFormThread.DisableComObjectEagerCleanup(); 208 WaitingAndProgressFormThread = null; 209 wpf = null; 210 } 211 212 #endregion 213 } 214 }
整个解决方案我会上传的!!
如果喜欢我的文章可以粉我!!!
本文系本人原创,源代码及文章引用转载请注明出处!!谢谢!
源码下载地址:http://files.cnblogs.com/files/lgmbk/UserControlTest.zip