Skip to content

ObserveOnCurrentSynchronizationContext

1. 概要

ObserveOnCurrentSynchronizationContext は、購読時点の SynchronizationContext.Current をキャプチャし、その上で通知を配信するオペレーターです。ObserveOn(SynchronizationContext.Current!) のショートカットとして機能します。UI フレームワークにおいて、バックグラウンド処理の結果を UI スレッドで受け取る際に便利です。

2. シグネチャ

デフォルト

csharp
public static Observable<T> ObserveOnCurrentSynchronizationContext<T>(
    this Observable<T> source)

購読時に SynchronizationContext.Current をキャプチャし、以降の通知をそのコンテキスト上で配信します。購読時に SynchronizationContext.Currentnull の場合は ThreadPool 上で通知を配信します。

3. マーブルダイアグラム

ObserveOnCurrentSynchronizationContext のマーブルダイアグラム

購読時点の SynchronizationContext がキャプチャされ、すべての通知がそのコンテキスト上で配信されます。

4. サンプルコード

csharp
// UI スレッドから購読する場合、通知も UI スレッドで受け取れる
observable
    .ObserveOnCurrentSynchronizationContext()
    .Subscribe(x => label.Text = x.ToString());

// バックグラウンド処理と組み合わせる
Observable.Create<int>(observer =>
    {
        Task.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                observer.OnNext(i);
            }
            observer.OnCompleted();
        });
        return Disposable.Empty;
    })
    .ObserveOnCurrentSynchronizationContext()
    .Subscribe(x => UpdateUI(x)); // UI スレッドで実行される

5. 補足

Unity のメインスレッド上で呼び出した場合、SynchronizationContext.Current には Unity のメインスレッド用コンテキストが設定されていることがあります。その場合、ObserveOnCurrentSynchronizationContext() はそのコンテキストへ通知をポストします。

ただし Unity では、R3.Unity が提供する ObserveOnMainThread を使う方が明確です。ObserveOnMainThread()UnityFrameProvider.Update を使って Unity の PlayerLoop に通知を戻すため、「Unity メインスレッドで受け取る」という意図がコード上でもはっきりします。Unity API や GameObject / Component を更新したい場合は、基本的に ObserveOnCurrentSynchronizationContext() ではなく ObserveOnMainThread() を使用してください。

csharp
observable
    .ObserveOnMainThread()
    .Subscribe(x => UpdateGameObject(x))
    .AddTo(this);

ObserveOnCurrentSynchronizationContext() は、WPF / WinForms / Blazor など SynchronizationContext を中心にスレッドを表現する環境向けのショートカットとして使うのが自然です。