2010-12-14 30 views
2

私の理解によれば、Dispatcher.InvokeとDispatcher.BeginInvokeはUIスレッドで実行されますが、Invokeは同期で、BeginInvokeは非同期です。このコードを使用すると問題が発生します。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で、私は別のスレッドがit.IがWCFサービスからこれを呼び出しています所有しているため

呼び出し元のスレッドがこのオブジェクトにアクセスすることはできません」と言ってはInvalidOperation例外を取得していますUseSynchronizationContextで実行= falseを.Can誰もが、この動作を説明する?

+0

「EDisc.App」の種類は何ですか? – JaredPar

+0

これはApplicaionオブジェクトのクラス名です.Application x:Class = "EDisc.App" – Rohit

答えて

2

BeginInvokeInvokeの両方が仕事をするためにBeginInvokeImplと呼ばれる内部メソッドを呼び出すことになりますされています。違いはInvokeが、その後compleする操作を待っていることですteを返す前に。

そして、もう一つ別の違いがあります:あなたは、あなたが実際に直接BeginInvokeImplを介さずにメソッドを呼び出しますDispatcherPriority.SendInvokeを使用している UIスレッド上に既にある場合は、操作がメッセージキューを介さずに処理されていることを意味します。 (Sendを使用していない場合は、操作よりも高いプロパティですでにキューイングされている他のメッセージが最初に処理されます)。

しかし、おそらくあなたはここのUIスレッドにはないので - あなたはいくつかのWCFコールバック - 特別な場合は適用されません。したがって、Invokeは、BeginInvokeと同じ基本実装を呼び出すことになります。

あなたが提供した情報から、ここにどこかに詳細がないことが推測されます。表示されたコードは、おそらくアプリケーション内に複数のUIスレッドがあり、発生するページがCurrentPageに属していない限り、正常に動作するはずです。

複数のUIスレッドがある場合は、複数のディスパッチャがあるため、現在のApplicationオブジェクトのディスパッチャを介してすべてをプッシュすることはできません。タッチする予定のUI要素のいずれかに適切なディスパッチャを取得する必要があります。

ちなみに、いくつかのワーカースレッドやコールバックにUIオブジェクト(ページなど)を作成すると、誤って複数のUIスレッドが作成される可能性があります。どこかでやったことは可能でしょうか?

+0

私はdataintensive操作を行うためにbackgroudthreadを使用しています。しかし、問題のコードを呼び出すときはいつでも、私のUiは完全に反応します(バックグラウンドスレッドは関係ありません)。 – Rohit