2010-12-14 90 views
2

根據我的理解Dispatcher.Invoke和Dispatcher.BeginInvoke在UI線程上執行,唯一的區別是Invoke是同步的,Be​​ginInvoke是異步的。我的問題是當我使用此代碼線程問題與Dispatcher.Invoke和Dispatcher.BeginInvoke

EDisc.App.Current.Dispatcher. 
       Invoke(
           DispatcherPriority.Normal, new Action(delegate 
           { 
            context = NavigationManager.CurrentPage.DataContext; 
           })); 

返回上下文的值。但是與下面的代碼

EDisc.App.Current.Dispatcher. 
       BeginInvoke(
           DispatcherPriority.Normal, new Action(delegate 
           { 
            context = NavigationManager.CurrentPage.DataContext; 
           })); 

上下文爲null,並且我得到InvalidOperation異常說「,因爲不同的線程擁有它。我是從一個WCF服務調用此

調用線程不能訪問此對象,與UseSynchronizationContext執行=假。可有人解釋這種現象?

+0

EDisc.App'的類型是什麼? – JaredPar 2010-12-14 07:35:04

+0

它是應用程序對象的類名。應用程序x:Class =「EDisc.App」 – Rohit 2010-12-14 08:18:42

回答

2

兩個BeginInvokeInvoke最終會打電話叫BeginInvokeImpl做工作的內部方法,所不同的是Invoke然後等待操作COMPLE在返回之前。

而且還有另外一個區別:如果你已經是你使用DispatcherPriority.SendInvoke實際上會調用該方法的情況下直接通過BeginInvokeImpl在UI線程上,這意味着操作不通過消息隊列會處理。 (如果你沒有使用Send,那麼任何其他消息已經排在比你的操作更高的屬性將被首先處理。)

但是既然你大概不在UI線程 - 你在一些WCF回調 - 特殊情況不適用。因此Invoke最終會調用與BeginInvoke相同的底層實現。

從您提供的信息中,我不得不猜測在這裏有一處遺漏的細節。你顯示的代碼應該可以正常工作,除非你的應用程序中有多個UI線程,並且碰巧在CurrentPage中的頁面不時地屬於不同的線程。

如果你確實有多個UI線程,那麼你正在使用的方法 - 通過當前的Application對象的調度程序推送所有內容 - 是行不通的,因爲你將擁有多個調度程序。您需要爲您計劃觸摸的任何UI元素獲得正確的調度程序。

順便說一句,如果您在某個工作線程或回調中構建一個UI對象(例如Page),您可能會意外終止多個UI線程。你有可能在某個地方做過嗎?

+0

我已經使用backgroudthread來執行數據操作。然而,無論何時我調用有問題的代碼,我的UI都完全響應(不涉及後臺線程)。 – Rohit 2010-12-14 13:19:30