13

私はwinformアプリケーションを持っており、次のような監視可能なセットアップがあります。

Form form = new Form();
Label lb = new Label();
form.Controls.Add(lb);

Observable.Interval(TimeSpan.FromSeconds(1))
          .Subscribe(l => lb.Text = l.ToString());

Application.Run(form);

フォームを作成したメインスレッドでは実行されないため、これは機能しませんl => lb.Text = l.ToString()が、このスレッドで実行する方法がわかりません。IObservable.SubscribeOnどちらかISchedulerを使用する必要があるとSynchronizationContext思いますが、メインスレッドの同期コンテキストを取得する方法がわかりません。見つけたスケジューラーは、、、、、などの静的プロパティSchedulerのみScheduler.CurrentThreadでしImmediateNewThread。どれもうまくいきませんでした。TaskPoolThreadPool

私のRxバージョンは1.0.10621です。

4

1 に答える 1

26

質問を投稿した直後に、解決策が見つかりました。

Form form = new Form();
Label lb = new Label();
form.Controls.Add(lb);

Observable.Interval(TimeSpan.FromSeconds(2))
          .ObserveOn(SynchronizationContext.Current)
          .Subscribe(l => lb.Text = l.ToString());

Application.Run(form);

このリンクは役に立ちました。2つのメモ:

  • すべてのスレッドに同期コンテキストがあるわけではありませんが、スレッドで作成される最初のフォームはそのスレッドの同期コンテキストを設定するため、UIスレッドには常に同期コンテキストがあります。
  • 正しい方法はObserveOn、ではなくSubscribeOnです。現時点では、理由を知るのに十分な知識がないので、コメント内のリンクをいただければ幸いです。

編集:このリンクの最初の部分のおかげで、との違いについてもっと理解できるようにObserveOnなりSubscribeOnました。要するに:

  • 同期コンテキストで監視するobservableは、そのコンテキストからIObserverメソッド(OnNextおよびフレンド)を呼び出します。私の例では、メイン/ UIスレッドを監視しているため、クロススレッドの例外は発生しません。
  • SubscribeOnはもう少し複雑なので、次に例を示します。Concatはいくつかのオブザーバブルを取得し、それらを1つの長いオブザーバブルに結合します。オブザーバブルが呼び出されるOnCompletedと、結合されたオブザーバブルはそのサブスクリプションを破棄し、次のオブザーバブルにサブスクライブします。これはすべて、を呼び出したスレッドで発生しますがOnCompleted、オブザーバブルのサブスクライブに問題が発生する可能性がありますObservable.FromEvent。たとえば、UIスレッド以外のスレッドからイベントハンドラーを追加するとSilverlightがスローされ、WinFormsとWPFは次の場合にスローされます。複数の異なるスレッドからイベントハンドラーを追加します。SubscribeOnobservableが基になるイベントに接続するスレッドを制御できるようになります。
于 2011-09-14T14:36:56.833 に答える