Silverlight如同WPF與以前的Windows Form程式一般,UI的部分都在單一的執行緒下面執行。在一個WPF的用程式起始的過程中有兩個執行緒
Silverlight如同WPF與以前的Windows Form程式一般,UI的部分都在單一的執行緒下面執行。在一個WPF的用程式起始的過程中有兩個執行緒:
1. UI執行緒
2. 背景執行緒,並協助UI執行緒 (DispatcherObject)
在一個WPF/Silverlight應用程式中絕大部分的UI元件都是繫結到UI執行緒,如果您在非UI 執行緒要變更UI的狀態就會得到UnauthorizedAccessException,如下使用WebRequest向其他的Web要求資料的範例程式:
1: HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/XmlSerializerSilverlightApplication1/XmlSerializerHandler.ashx");
2: request.ContentType = "application/xml";
3: request.Method = "POST";
4:
5: AsyncCallback ac = asyncResult =>
6: {
7: if (asyncResult.IsCompleted)
8: {
9: Stream stream = request.EndGetResponse(asyncResult).GetResponseStream();
10: StreamReader reader = new StreamReader(stream);
11: string ResponseStr = reader.ReadToEnd();
12:
13: List<Employees> mmc = new List<Employees>();
14: System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(mmc.GetType());
15: System.Xml.XmlReader XmlReader = XmlReader.Create(new StringReader(ResponseStr));
16: try
17: {
18: mmc = serializer.Deserialize(XmlReader) as List<Employees>;
19: dataGrid1.ItemsSource = mmc; //會出現UnauthorizedAccessException錯誤
20: }
21: catch (Exception ex)
22: {
23: throw ex;
24: }
25: finally
26: {
27: reader.Close();
28: }
29: }
30: };
31: request.BeginGetResponse(ac, request);
如下IDE扔回來的錯誤畫面:
在WPF/Silverlight 中任何UI 執行緒上的處理都是透過Dispatcher來傳送並處理,因此最簡單的方式就是透過Dispather的BeginInvoke()方法來傳送,上面會變更UI的程式碼也只有一行,所以基本上只要將dataGrid1.ItemsSource = mmc; 與 request.BeginGetResponse(ac, request);這兩行的程式碼的部分放入 Dispatcher.BeginInvoke() 之中,因為在Silverlight 中同樣也沒有同步的Invoke()方法,這個是與WPF其中一個不同的地方。
所以上述的程式碼應該會變成如下:
1: HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/XmlSerializerSilverlightApplication1/XmlSerializerHandler.ashx");
2: request.ContentType = "application/xml";
3: request.Method = "POST";
4:
5: AsyncCallback ac = asyncResult =>
6: {
7: if (asyncResult.IsCompleted)
8: {
9: Stream stream = request.EndGetResponse(asyncResult).GetResponseStream();
10: StreamReader reader = new StreamReader(stream);
11: string ResponseStr = reader.ReadToEnd();
12:
13: List<Employees> mmc = new List<Employees>();
14: System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(mmc.GetType());
15: System.Xml.XmlReader XmlReader = XmlReader.Create(new StringReader(ResponseStr));
16: try
17: {
18: mmc = serializer.Deserialize(XmlReader) as List<Employees>;
19:
20: this.Dispatcher.BeginInvoke(delegate()
21: {
22: dataGrid1.ItemsSource = mmc;
23: }
24: );
25: }
26: catch (Exception ex)
27: {
28: throw ex;
29: }
30: finally
31: {
32: reader.Close();
33: }
34: }
35: };
36: this.Dispatcher.BeginInvoke(delegate()
37: {
38: request.BeginGetResponse(ac, request);
39: });
程式中紅色部分即是增加的部分,因為在Silverlight 中也只有非同步的BeginInvoke() 可以使用,它所接受的便是一個delegate的委派,因此直接將非同步的起始點,也就是request.BeginGetResponse(ac, request); 放入BeginInvoke() 即可。同樣的dataGrid1.ItemsSource = mmc;也是相同方式,這是會實際更動UI執行緒的程式碼。此動作會告知UI 執行緒,直接插入UI執行緒的駐列中,表示還有一件UI工作要處理。因此程式可以正常的執行了。
一個執行緒的技巧,希望對使用到的朋友有幫助 :D
謝謝各位!
簽名:
學習是一趟奇妙的旅程
這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。
軟體開發之路(FB 社團):https://www.facebook.com/groups/361804473860062/
Gelis 程式設計訓練營(粉絲團):https://www.facebook.com/gelis.dev.learning/
如果文章對您有用,幫我點一下讚,或是點一下『我要推薦』,這會讓我更有動力的為各位讀者撰寫下一篇文章。
非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^