WPF 利用子線程彈出子窗體的研究


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

  實際上這里只有兩個難點需要處理,一個就是如何讓子窗體遮擋主窗體並位於主窗體中間,另一個就是委托及跨線程訪問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         }
View Code

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         }
View Code

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 }
View Code

整個解決方案我會上傳的!!

如果喜歡我的文章可以粉我!!!

 

本文系本人原創,源代碼及文章引用轉載請注明出處!!謝謝!

源碼下載地址:http://files.cnblogs.com/files/lgmbk/UserControlTest.zip

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM