普通のやり方だとasyncなメソッドを呼び出すのはasyncメソッドからでないとダメ、そのせいで既存のプログラムやクラスにasyncメソッドを追加するのはけっこうめんどう
という呪縛から解放するための小ネタ。
あくまで雛型なので、これを元に必要に応じてエラーやキャンセルの場合の処理を追加することで実用的になると思います。
static class AsyncWrapper{
//返り値あり
static TResult Await<TResult>(Func<Task<TResult>> asyncFunc)
{
//Task.Runを使わず直接asyncFuncを呼ぶとデッドロックの可能性あり
Task<TResult> task = Task.Run<TResult>(asyncFunc);
task.Wait();
return task.Result;
}
//返り値なし
static void Await(Func<Task> asyncFunc)
{
Task task = Task.Run(asyncFunc);
task.Wait();
}
}
使用例
Bluetoothのデバイスインスタンスを取得
//using Windows.Devices.Bluetooth;
UInt64 bleAddress = 0xff00ff00ff00ff00;//ダミーアドレス
//ラムダ式を渡す場合はAwait<返り値の型>と明示する必要あり
//IAsyncOperationなどを返すメソッドはAsTask()で明示的にTaskに変換する
var bleDevice = AsyncWrapper.Await<BluetoothLEDevice>(() =>
BluetoothLEDevice.FromBluetoothAddressAsync(bleAddress).AsTask());
追記
「メソッドの拡張メソッド」というわけのわからんボケをやってたので修正しました。
あと.NETでは「(普通の)メソッドはオブジェクトではない」ため、ほとんどの場合は「AsyncWrapper.Await()の引数としてラムダ式を渡す」形になりそう。