【轉】Silverlight 跨線程訪問無效

Silverlight 的許多請求基本都是異步的,用WCF也好,WEBCLIENT也好,都會進行異步請求,並提供一個事件用於執行回調。在使用WCF和WEBCLIENT與服務器通信的時候通常我們都不會遇到什麼麻煩,因爲WCF的類方法和WEBCLIENT都是在主線程上執行和委託事件的,理所當然,回調事件也是在主線程上運行,所以一馬平川的就使用了。但是當我們用到Socket或者HttpWebRequest(HttpWebRequest我自己本身沒用但是看別人在用的時候遇到相同的問題)的時候回調事件中如果試圖修改UI之類的時候就會出現“跨線程訪問無效的”錯誤異常。

爲什麼呢?以Socket來說,異步的回調事件並不是在Socket對象上定義的,而是在其SocketAsyncEventArgs 對象上定義的,要實現異步,Silverlight當然會自己創建一個子線程去運行這個異步事件,所以,雖然在主線程上定義了Socket和SocketAsyncEventArgs,但是Socket執行異步方法後,將SocketAsyncEventArgs委託給了異步子線程,所以在SocketAsyncEventArgs上定義的事件回調也是子線程的,這樣的話,子線程的回調函數當然就不允許去操作主線程上的對象了,因此Socket的參數回調事件上修改UI等,會引發 “跨線程訪問無效的”異常。

如何解決呢?

Silverlight提供了一個同步上下文的類 SynchronizationContext 類(System.Treading命名空間下) ,該類提供在各種同步模型中傳播同步上下文的基本功能。

也就是說,你可以使用該類,不同線程上方法調度到某一指定線程上。

下面用Socket爲例:

Xaml:很簡單,就是一個按鈕和一個文本框,按鈕有一個Click事件,綁定到OnSend方法

 

  

代碼部分:

  

 爲了集中說明問題,省略很很多部分,該代碼的功能只是創建一個Socket和其參數,參數綁定一個完成回調事件,然後執行連接,連接好之後,引發回調OnOperationCompleted。

如果,我們在回調函數上直接寫上txtToSend.Text="XXX",一定會引發跨線程的異常,因此,我們用之前在主線程上定義的SynchronizationContext 的實例syn的Post方法,將回調子線程的操作調度到主線程上的GetText方法上,並傳遞個參數"OK",這樣在回調函數將操作調度到GetText方法,然後GetText方法中就可以進行修改UI上的屬性了。


在前面定義 SynchronizationContext的時候,我們將它實例化爲SynchronizationContext.Current,即當前線程,定義並實例化SynchronizationContext的時候是在主線程上進行的,因此 Current指的上下文或線程 就是主線程,所以在後來的回調函數中,調度GetText就是調度到主線程上,主線程可以修改UI所以GetText可以修改UI。


大概的原理和方法就是如此,文中提到的一些思路爲個人理解,如果與實際有差,還請見諒。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/banmuhuangci/archive/2009/05/13/4176870.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章