読者です 読者をやめる 読者になる 読者になる

.NET 4.6 の async/await の改善が地味に嬉しい

そろそろ仕事先の Framework バージョンを上げたいなと思って .NET 4.6 について今更ちゃんと調べ始めました。

正直多すぎて全部追えてないんですが、 async/await 周りの改善が嬉しかったのでブログに書きます。

ドキュメント

dotnet/dotnet46-changes.md at master · Microsoft/dotnet · GitHub

DotNet4.6.md · GitHub

.NET Framework 4.6 におけるランタイムの変更点

AsyncLocal クラスの追加

AsyncLocal というクラスが追加されました。
非同期スコープにおけるスタック型 (っぽい) データストアです。

スタック型ぽいってのは、インスタンスがスタックみたいな動きをするんじゃなくて、非同期スコープごとにインスタンスがスタックに積まれていくイメージです。我々開発者から見た AsyncLocal<T> は単なる一つの値を格納できる箱でしかなく、そこに領域を Push/Pop するのはフレームワークです。

訳分からないと思うので、分かりやすくて詳しい説明は id:xin9le さんの ブログ をご覧ください。

Task クラスに便利プロパティ/メソッド追加

CompletedTask プロパティ
FromCanceled メソッド
FromException メソッド

非同期処理で、今まで面倒というか全然直感的じゃなかった記述をより分かりやすく書けるようになりました。TaskResult とか何回書いたか分かりません。

こちらも分かりやすくて詳しい説明は id:xin9le さんの ブログ をご覧ください。

Task, Task<T> が呼出元スレッドのカルチャとUIカルチャを継承するようになった

で、これが本題です。

詳細は カルチャとタスク ベースの非同期操作 を参照していただくといいです。
とはいえ、機械翻訳にも程があるので原文も一緒に => Culture and task-based asynchronous operations

簡単に言うと Task 使ったり async/await 使ったときに、呼出先デリゲートと呼出元のカルチャが同じになりました。ってタイトルのまんまですね。コード見ましょうコード。

static void Main(string[] args)
{
    // ちなみに ↓ も 4.6 から CultureInfo.CurrentCulture = new CultureInfo("en-US") と書けるように。
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

    var now = DateTime.Now;
    Task.Run(() => Console.WriteLine(now)).Wait();
    Task.Run(async () => await Task.Run(() => Console.WriteLine(now))).Wait(); // あんま意味ないけど
}

// .NET 4.5.2
// 2015/09/07 21:34:15
// 2015/09/07 21:34:15

// .NET 4.6
// 9/7/2015 9:35:28 PM
// 9/7/2015 9:35:28 PM

これは便利です。
今までカルチャを引き継ぐようにした非同期ヘルパーを自前で作ったりしてましたが、 .NET 4.6 からはそんなものは不要になります。早くバージョン上げたいですね。

以上、傘がなくて帰れない現場からお送りしました。