LoginSignup
6
2

More than 5 years have passed since last update.

非asyncメソッドからasyncメソッドを使う拡張メソッド(リベンジ)

Last updated at Posted at 2018-12-10

去年書いたやつがクソすぎたのでけっこう後悔していたんだけど、今日気がついたやりかた。

@laughterさんが修正してくれた改良前のコード
static class TaskExtention {
  //返り値なし
  public static void NoWait(this Task task, Action<Task> action = null, CancellationToken? ct = null)
  {
    if (action != null) {
      if (ct != null) {
        task.ContinueWith(action, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(action).ConfigureAwait(false);
      }
    } else {
      if (ct != null) {
        task.ContinueWith(_ => {}, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(_ => {}).ConfigureAwait(false);
      }
    }
  }

  //返り値あり
  public static void NoWait<TResult>(this Task<TResult> task, Action<Task<TResult>> action = null, CancellationToken? ct = null)
  {
    if (action != null) {
      if (ct != null) {
        task.ContinueWith(action, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(action).ConfigureAwait(false);
      }
    } else {
      if (ct != null) {
        task.ContinueWith(_ => {}, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(_ => {}).ConfigureAwait(false);
      }
    }
  }
}

改良版

@laughter さんの修正案コメント

??とCancellationToken.Noneを使うとキャストを消せる

を見て「パラメータ省略時の値にCancellationToken.None」を指定できたらもっとすっきりするのになー」と思ってたら、default(CancellationToken)と書くことで可能 アンド task.ContinueWith(action, CancellationToken.None)task.ContinueWith(action)と同等との記述を見つけたのでさらに改良。
ついでにactionの方の扱いも修正して、if文のネストがごっそりなくなりました。

static class TaskExtention
{
  //返り値なし
  public static void NoWait(this Task task, Action<Task> action = null, CancellationToken ct = default)
  {
    task.ContinueWith(action ?? (_ => { }), ct).ConfigureAwait(false);
  }

  //返り値あり
  public static void NoWait<TResult>(this Task<TResult> task, Action<Task<TResult>> action = null, CancellationToken ct = default)
  {
    task.ContinueWith(action ?? (_ => { }), ct).ConfigureAwait(false);
  }
}

使い方

使い方
void NoAsyncMethod(CancellationToken ct)
{
  //返り値なし、後処理なし
  AsyncMethod().NoWait();

  //返り値あり、後処理あり、CancellationTokenあり
  AsyncMethodWithResult(ct).NoWait(task => { var result = task.Result; }, ct);
}

呼び出し側で実行結果を受け取ることはできない。
「呼び出したいメソッドがasyncなやつしかないけど、呼ぶ側はasyncにできない。処理完了を待ったり結果を受け取る必要はなくて投げっぱなしでOK」といったケース用のお手軽メソッドなので、そういう制約を気にする必要がないときに使うものです。

6
2
1

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
6
2