Skip to content

SubscribeOnCurrentSynchronizationContext

1. 概要

SubscribeOnCurrentSynchronizationContext は、購読時点の SynchronizationContext.Current をキャプチャし、その上で購読処理(Subscribe および Dispose)を実行するオペレーターです。SubscribeOn(SynchronizationContext.Current!) のショートカットとして機能します。

2. シグネチャ

デフォルト

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

購読時に SynchronizationContext.Current をキャプチャし、ソースへの購読処理をそのコンテキスト上で実行します。購読時に SynchronizationContext.Currentnull の場合は ThreadPool 上で購読処理を実行します。

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

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

購読時点の SynchronizationContext がキャプチャされ、ソースへの実際の購読がそのコンテキスト上で実行されます。

4. サンプルコード

csharp
// 現在の SynchronizationContext で購読処理を実行
observable
    .SubscribeOnCurrentSynchronizationContext()
    .Subscribe(x => Console.WriteLine($"値: {x}"));

// ObserveOn と組み合わせる
observable
    .SubscribeOnCurrentSynchronizationContext()
    .ObserveOn(TimeProvider.System)
    .Subscribe(x => ProcessInBackground(x));

5. 補足

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

ただし Unity では、R3.Unity が提供する SubscribeOnMainThread を使う方が明確です。SubscribeOnMainThread()UnityFrameProvider.Update を使って Unity の PlayerLoop 上で購読処理を開始するため、「Unity メインスレッドで購読する」という意図がコード上でもはっきりします。購読開始時に Unity API を触る Observable では、基本的に SubscribeOnCurrentSynchronizationContext() ではなく SubscribeOnMainThread() を使用してください。

csharp
observable
    .SubscribeOnMainThread()
    .Subscribe(x => Process(x))
    .AddTo(this);

SubscribeOnMainThread() が制御するのは購読処理の実行場所であり、通知の配信場所ではありません。OnNext などを Unity メインスレッドで受け取りたい場合は、ObserveOnMainThread を併用してください。SubscribeOnCurrentSynchronizationContext() は、WPF / WinForms / Blazor など SynchronizationContext を中心にスレッドを表現する環境向けのショートカットとして使うのが自然です。