しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC 4 の新機能、タスク対応の非同期コントローラを使う

WebMatrix だったり MVC 4 だったりで忙しいですが、いつも通り気まぐれで紹介していきたいと思います。

さて、今回は ASP.NET MVC 2 から追加された非同期コントローラが、MVC 4 から .NET 4 で追加された Task クラスに対応したので、それを紹介したいと思います。

MVC 3 までの非同期コントローラに関しては 非同期コントローラ使ってみた - しばやん雑記 を参照してください。基本的には MVC 4 でも同じ記法で非同期処理を書くことが出来ますが、メソッドを 2 つ用意する必要があるので値の引き渡しや、処理が分離してしまうので継続する処理が書きにくいという欠点がありました。

しかし、MVC 4 からは Task クラスを返すことが出来るので、そのあたりの不便さが一気に解消されています。使い方は Task を返すアクションを定義するだけです。アクションの命名規約などは特にありません。

前回のブログエントリで書いたアクションを書いて比較してみたいと思います。まずは素直に Task を返すアクションを書いてみます。

public Task<ActionResult> Index()
{
    // 新しくタスクを開始
    return Task.Factory.StartNew(() =>
    {
        var twitter = new TwitterService();

        // 同期版のメソッドを呼び出す
        var tweets = twitter.GetTimeline();

        return (ActionResult)View(tweets);
    });
}

あまりよくないんですが、同期メソッドを Task で包んで処理しています。最後に ActionResult にキャストしている理由は、Task から Task へ暗黙的なキャストが行えないからです。

これはスコープも深くなるし、最後にキャストが必要になるしと美しくないですね。それでは、C# 5.0 で追加されるであろう async/await キーワードを使って同じ処理を書いてみましょう。

// アクションに async を指定しておく
public async Task<ActionResult> Index()
{
    var twitter = new TwitterService();

    // GetTimelineAsync は Task<T> を返すメソッド
    // 処理結果を await 付けて受け取る
    var tweets = await twitter.GetTimelineAsync();

    return View(tweets);
}

一目見るだけで違いが分かると思いますが、async/await キーワードのおかげで同期アクションと同じように書けるようになっています。

ちなみに手元の VS2010 では async/await が Async CTP 最新版を入れても動作しなかったので、今回の確認は全て VS11 DP で行いました。共存可能みたいなので、インストールするのがいいと思います。