一般來說子線程都是用來處理數據的,主窗體用來實現展現,但是有些時候我們希望子窗體實現等待效果,遮擋主窗體並使主窗體邏輯正常進行,這個業務需求雖然不多,但是正好我們用到了,於是我打算把研究成果寫在這了。稍后我會上傳我的代碼,包含測試程序以及之前兩邊博文談到的控件,這里我還實現了一個類似雷達掃描的等待窗體,大家可以稍后查看。
實際上這里只有兩個難點需要處理,一個就是如何讓子窗體遮擋主窗體並位於主窗體中間,另一個就是委托及跨線程訪問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
