C#でコールバックをTaskにしてawaitしたい
C#でコールバックの値を同期的に取得したい時がある。
Rxを使ってJavascriptのPromise的なことをする。
// コールバックで値を返すメソッド private void Foo(Action<string> arg) { arg("qawsedrf"); }
// コールバックの値を取得してTaskにして返すメソッド private Task<string> Bar() { return Observable.Create<string>(observer => { Foo(a => { observer.OnNext(a); observer.OnCompleted(); }); return null; }).ToTask(); }
string value = await Bar(); Console.WriteLine(value); // qawsedrf
Observable.Createでコールバックからの値を流すObservableを作り、 ToTaskでTaskに変換できる。
これを活用して以下のようなことができる。
string dataPath = await Observable.Create<string>(observer => { return Observable.Return(Unit.Default).ObserveOnMainThread().Subscribe(_ => { observer.OnNext(Application.persistentDataPath); observer.OnCompleted(); }); }).ToTask();
Unityの場合、メインスレッド上でなければUnityAPIを呼び出すことができないが、 こうすることでUnityAPIである Application.persistentDataPath の呼び出しだけメインスレッドで行う。
こんなメソッドを作ればスレッドに囚われないGetComponentができる。
private Task<T> GetComponent2<T>(GameObject gameObject) { return Observable.Create<T>(observer => { return Observable.Return(Unit.Default).ObserveOnMainThread().Subscribe(_ => { T component = gameObject.GetComponent<T>(); observer.OnNext(component); observer.OnCompleted(); }); }).ToTask(); }
Rigidbody rb = GetComponent2<Rigidbody>(this.gameObject)
コメント
コメントを投稿