xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

.NET Framework 4.5.3でのTask型への機能追加

しばらく前になりますが、2014/10/6 に Visual Studio 14 CTP 4 がリリースされました。そのリリースの中で .NET Framework も更新され、バージョン 4.5.3 となりました。少し触っていたら、Task 型 (System.Threading.Tasks 名前空間) に新しいプロパティとメソッドが追加されていたのでご紹介します。

CompletedTask プロパティ

たとえば非同期な戻り値を持つインターフェースのモック実装をする際など、メソッドの中はとりあえずで同期処理として書いておいて、戻り値だけ Task 型として合わせたい場合があります。そんなとき、これまでだったら大体以下のように書いていたと思います。

static Task DoSomethingAsync()
{
  //return Task.Run(() => {});  //--- 意味のないスレッドを起こすのはイヤ
    return Task.FromResult(0);  //--- 完了状態のTaskを生成
}

戻り値として Task<int> 型がほしい訳では全くないですが、とりあえず完了状態の Task を簡単に作るために FromReuslt メソッドを利用したりして逃げていました。それが、.NET Framework の次期バージョンである 4.5.3 では完了済みの Task をそのまま取得するためのプロパティが提供されるようになりました。おかげで上記のような「意味のない」コードが消えます。

static Task DoSomethingAsync()
{
    return Task.CompletedTask;
}

FromException メソッド

完了状態以外にも、エラー状態に遷移した Task を生成したい場合もあります。これまでは TaskCompletionSource 型を利用して以下のような感じで書いていました。

static Task DoSomethingAsync()
{
    var tcs = new TaskCompletionSource<int>();  //--- TaskCompletionSourceを利用 (int型には意味はない)
    tcs.SetException(new Exception());          //--- もしくはTrySetException
    return tcs.Task;
}

それをよりコンパクトに、分かりやすく記述できるようなります。

static Task DoSomethingAsync()
{
    return Task.FromException(new Exception());
}

FromCanceled メソッド

それ以外にも、キャンセル状態に遷移した Task を生成したい場合もあります。これまでは先のエラー状態と同様に TaskCompletionSource 型を利用して以下のような感じで書いていました。

static Task DoSomethingAsync()
{
    var tcs = new TaskCompletionSource<int>();
    tcs.SetCanceled();  //--- もしくはTrySetCanceled
    return tcs.Task;
}

それを以下のように書けるようになります。

static Task DoSomethingAsync()
{
  //return Task.FromCanceled(CancellationToken.None);  //--- これだとArgumentOutOfRangeExceptionが発生
    return Task.FromCanceled(new CancellationToken(true));
}

引数に渡す CancellationToken 型のインスタンスIsCancellationRequested プロパティが true を返す状態でなければなりません。さもなければ ArgumentOutOfRangeException が飛びます。個人的には引数として CancellationToken を与えること自体面倒に感じますし、しかもキャンセル状態でなければ例外になる仕様は全然嬉しくありません。これに関しては正式版のリリースまでに仕様 (およびメソッド名) が変わることに期待しています。