LoginSignup
5
4

More than 5 years have passed since last update.

非asyncメソッドからasyncメソッドを使うためのラッパーメソッド

Last updated at Posted at 2017-11-13

普通のやり方だと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()の引数としてラムダ式を渡す」形になりそう。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4