【Unity】【UniRx】UniRxで処理するスレッドを操作する方法まとめ

UniRxで処理するスレッドを操作する方法をまとめました。

unity2019.2.5

Schedulerが指定できるFactoryメソッド

まず、一部のObservableは生成するときに引数としてSchedulerというものが指定できます。
このSchedulerは処理するスレッドを定義するもので、例えば以下のように書けばメインスレッドで処理できます。

using UnityEngine;
using UniRx;
using System.Threading;
using System;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        Observable
            .Interval(TimeSpan.FromSeconds(1), Scheduler.MainThread) // メインスレッドを指定
            .Subscribe(_ => Debug.Log(Thread.CurrentThread.ManagedThreadId))
            .AddTo(this);
    }
}

このSchedulerを以下のように書き換えれば、メインスレッド以外で処理を行うことができます。

using UnityEngine;
using UniRx;
using System.Threading;
using System;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        Observable
            .Interval(TimeSpan.FromSeconds(1), Scheduler.ThreadPool) // スレッドプールを指定
            .Subscribe(_ => Debug.Log(Thread.CurrentThread.ManagedThreadId))
            .AddTo(this);
    }
}

このように、ファクトリメソッドの引数にSchedulerを持つObservableは処理するスレッドを制御できます。

StartとToAsyncはスレッドプールのSchedulerが使われる

Observableのファクトリメソッドに、Start()ToAsync()といったものがあります。
これらはサブスレッドでの非同期処理を簡単に書くためのファクトリメソッドです。

仕組みとしては内部的にスケジューラとして前述のScheduler.ThreadPoolが指定されています。
そのため下記のように書くだけで簡単に非同期処理が実現できます。

using UnityEngine;
using UniRx;
using System.Threading;
using System;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        // サブスレッドでの非同期処理が簡単に書ける
        Observable.Start(() => Debug.Log(Thread.CurrentThread.ManagedThreadId))
            .Subscribe()
            .AddTo(this);
    }
}

Observable.CreateとSubscribeOn

Observable.Create()SubscribeOn()を組み合わせると指定したスレッドで処理を行うObservableが作れます。

using UnityEngine;
using UniRx;
using System.Threading;
using System;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        // CreateでObservableを作る
        Observable.Create<Unit>(observer => {
            observer.OnNext(Unit.Default);
            observer.OnCompleted();
            return Disposable.Empty;
        })
        // SubscribeOnでスレッドを指定する
        .SubscribeOn(Scheduler.ThreadPool)
        .Subscribe(_ => Debug.Log(Thread.CurrentThread.ManagedThreadId));
    }
}

ストリームの途中で処理するスレッドを切り替えるObserveOn

ObserveOn()を使うと、ストリームの途中で処理するスレッドを切り替えることができます。

using UnityEngine;
using UniRx;
using System.Threading;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        Observable.Start(() => {}) // 別スレッドで開始
            .ObserveOnMainThread() // ここからはメインスレッドで処理
            .Do(_ => Debug.Log(Thread.CurrentThread.ManagedThreadId))
            .ObserveOn(Scheduler.ThreadPool) // ここからはスレッドプールで処理
            .Do(_ => Debug.Log(Thread.CurrentThread.ManagedThreadId))
            .Subscribe()
            .AddTo(this);
    }
}

関連

light11.hatenadiary.com

light11.hatenadiary.com