19

コードでロックを使用することについて非常に悪い気持ちがありますが、WindowBaseのディスパッチャーが存在し、どこでも使用したいと思っています。

たとえば、PRISMのEventAggregatorでイベントを公開するマルチスレッドシングルトンWCFサービスを使用すると、ペイロードは不変であり(データのみ)、ディスパッチャーを持つすべてのスレッドは、独自のディスパッチャーでデッドロックが発生することなく、イベントを適切に取得できます。(UIスレッドだけでなく、データベース呼び出しのあるスレッド、サービス呼び出しのあるスレッド、ログに記録するスレッド、またはUIをフリーズしたくないため、遅い呼び出しのある他のスレッドもあります)。

しかし、私の問題は、このディスパッチャーがWPFと結合されているため、どこでも使用すると少し罪悪感を感じることです。ディスパッチャーは、私のユースケース用に作成されたものではないと感じています。

WPFと組み合わせていない別のDispatcher実装が存在しますか?またはそれを悪用しても大丈夫ですか?

ありがとう、

アップデート

Paul Stovellが私に提供する解決策は、インターフェイスIDispatcherとWpf Dispatcherのアダプターを作成することです。これにより、テストが容易になります。このソリューションは、テストをリファクタリングし、テストでSynchronousDispatcherAdapterを使用できるようになったため、私にとっては良かったです(おかげで、テストでWPFのディスパッチャーを使用する必要がなくなりました)。

マルチパブリッシャー/サブスクライバーパターン(PRISMを使用)を使用しているため、BackgroundWorkerの代わりにDispatcherを使用することは理にかなっています。また、Dispatcherのおかげで、すべてのイベントハンドラーは、イベントにサブスクライブするスレッドで呼び出されます。これは、マルチスレッドの問題が発生する可能性がある唯一のポイントが私のイベントのペイロードにあることを意味します(私は彼を不変にしました)。

私のさまざまなスレッドは、それらの間で直接通信するのではなく、イベントをパブリッシュおよびサブスクライブするだけです。したがって、データベース呼び出し、ログ呼び出し、サービス呼び出し、UI呼び出しは異なるスレッドで実行され、相互に認識しません(サブスクライブしてパブリッシュするイベントについてのみ認識します)。

UIからリポジトリにいくつかの呼び出しを行う場合、バックグラウンドワーカーは理にかなっています。

しかし、私はこのサブスクライバー/パブリッシャーパターンを使用することを好むため、BackgroundWorkerを使用せずにデザインを見つけたいと思っています(コードが読みやすくなると思います)

4

3 に答える 3

16

Dispatcher (または BackgroundWorker) を使用する際の主な問題は、テスト ハーネスに実際に UI スレッドがない限り、テストが難しいことです。

解決策 1

SynchronizationContextを使用します。UI スレッドで呼び出す同じ機能を提供し、Windows または WPF で動作します。試着も可能です。

解決策 2

ディスパッチャは単なる別のサービスと考えてください。PRISM を使用すると、サービスと IOC に精通します。このようなサービスの使用方法は次のとおりです。

// Not a UI component
public class MyDomainService : IMyDomainService
{
   private readonly IDispatcher _dispatcher;

   public MyDomainService(IDispatcher dispatcher) 
   {
      _dispatcher = dispatcher;
   }

   private void GotResultFromBackgroundThread()
   {
       _dispatcher.Dispatch(() => DoStuffOnForegroundThread());
   }
}

これにより、プラットフォーム/テストをさまざまな実装で置き換えることができます。

これは、IDispatcherWPF 実装、およびテスト実装の例です。それらを他のサービスと同じように IOC コンテナに登録すると、UI と他のサービスの両方で利用できるようになります。

于 2009-01-28T07:46:59.053 に答える
2

はい、いいえ..それはレンダリングのことです..それ自体はスレッド化ではありません..

Dispatcher は優先度に基づいて作業項目を選択し、それぞれを最後まで実行します。すべての UI スレッドには少なくとも 1 つの Dispatcher が必要であり、各 Dispatcher は正確に 1 つのスレッドで作業項目を実行できます。このマイクロソフトからのこのリンクに従って。

自分で開始したスレッドは、自分で処理する必要があります。

情報については、この 1 つを確認してください: イベント ベースの非同期パターンを使用したマルチスレッド プログラミング

個人的には、スレッド化のニーズにバックグラウンド ワーカーを使用しています。

ベスト プラクティスはこちら

于 2009-01-28T07:38:49.490 に答える