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)
コメント
コメントを投稿