UniRx.Asyncで、UniTaskからIObservableに変換したものをいくつか、直列(同期的)に繋ぎたい。
目的は、非同期的に呼び出されたいくつかの処理を同期させることです。
問題は、タイトルの方法が上手くいかず、原因がわからないことです。
また、もっと良いシンプルな方法があれば、教えてください。
まず、非同期的な処理をコルーチンで記述し、それをIObservableに変換したものをMergeしてConcatするということを考えました。
IEnumerator Cor1 () {
yield return new WaitForSeconds (3);
Debug.Log ("Cor1: waited 3 sec");
yield return null;
}
IEnumerator Cor2 () {
yield return new WaitForSeconds (1);
Debug.Log ("Cor2: waited 1 sec");
yield return new WaitForSeconds (9);
Debug.Log ("Cor2: waited 9 sec");
yield return null;
}
void DoCoroutineOnObservable () {
var a = new Subject<Unit> ();
var b = new Subject<Unit> ();
var obs1 = a.Select (_ => Observable.FromCoroutine (Cor1));
var obs2 = b.Select (_ => Observable.FromCoroutine (Cor2));
Observable.Merge (obs1, obs2).Concat ().Subscribe ();
// 発行
a.OnNext (Unit.Default);
b.OnNext (Unit.Default);
a.OnNext (Unit.Default);
}
これは想定通り、以下のように出力されます。
cor1: waited 3 sec
cor2: waited 1 sec
cor2: waited 9 sec
cor1: waited 3 sec
しかし、同様の方法でコルーチンをUniTaskに変えてみたのですが、上手くいきません。
async UniTask<Unit> Task1 () {
await UniTask.Delay (3000); // note! Delayはミリ秒指定
Debug.Log ("Task1: waited 3 sec");
return Unit.Default;
}
async UniTask<Unit> Task2 () {
await UniTask.Delay (1000);
Debug.Log ("Task2: waited 1 sec");
await UniTask.Delay (9000);
Debug.Log ("Task2: waited 9 sec");
return Unit.Default;
}
void DoUniTaskOnObservable () {
// ストリームの構築
var a = new Subject<Unit> ();
var b = new Subject<Unit> ();
var obs1 = a.Select (_ => Task1 ().ToObservable ());
var obs2 = b.Select (_ => Task2 ().ToObservable ());
Observable.Merge (obs1, obs2).Concat ().Subscribe ();
// 発行
a.OnNext (Unit.Default);
b.OnNext (Unit.Default);
a.OnNext (Unit.Default);
}
これは上手くいかず、以下のように出力されます。
Task2: waited 1 sec
Task1: waited 3 sec
Task1: waited 3 sec
Task2: waited 9 sec
2番目と3番目のTask1の出力は同時にされます。
つまり、全ての呼び出しが並行(非同期的)に行われているのです。
どのようにすれば、同期的に処理できるでしょうか?