async/awaitを用いた非同期ページの導入方法
それでは、実際にasync/awaitを用いた非同期ページをどのように導入するのか説明していきましょう。手順としては、以下のようになります。
- Web.configに同期コンテキスト設定を行う
- Webページごとに非同期処理を有効にする
- イベントハンドラー等で非同期処理を呼び出す
順に説明していきましょう。
Web.cofigに同期コンテキスト設定を行う
非同期処理は「同期コンテキスト(SynchronizationContext)(*2)」と切っても切れない関係にあります。async/awaitを用いた非同期ページでは非同期処理にTaskクラスを用いるため、Taskを基本とした同期コンテキストを使うよう、Web.configで指定する必要があります(リスト5)。
<appSettings> ... <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings>
この設定には、appSettingsセクションに、キーが"aspnet:UseTaskFriendlySynchronizationContext"、値が"true"のエントリを追加します。
非同期処理を別スレッドで行わせるためのAPIは、コンソール、Windowsフォーム、ASP.NETなど、プラットフォームによって異なります。こういった処理を統一的に扱うために用意された仕組みが、同期コンテキストです。その実態はShynchronizationContextクラスで、Postメソッドなどを使って非同期処理を制御することができます。それぞれのプラットフォームでは、専用のSynchronizationContextクラスの派生クラスが用意されていることもあります。
async/await構文を使った処理の内部では、現在動作しているスレッドのための同期コンテキストを取得し、その同期コンテキスト使って別のスレッドに処理を委譲します。詳しくは以下の記事を参照してください。
Webページごとに非同期処理を有効にする
非同期処理を有効にするには、PageクラスのAsyncプロパティにtrueを設定します。aspxファイルの@Pageディレクティブで設定するのが、もっとも簡単な方法でしょう(リスト6)。
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="LocationsDetail.aspx.cs" Inherits="LocationsDetail" Async="true" %>
イベントハンドラー等で非同期処理を呼び出す
次に、コードビハインド側で非同期処理を呼び出します(リスト7)。
// 更新処理 public void UpdateLocation(Location location) { // (1) 非同期処理を内包したPageAsyncTaskオブジェクト作成 var task = new PageAsyncTask(async () => { // モデル検証でエラーがあれば処理中断 if (!ModelState.IsValid) return; // ビジネスロジックの更新処理実行 var logic = new LocationLogic(); await logic.Update(location); // 場所参照画面に戻る BackToLocations(); }); // (2) PageAsyncTaskの登録 RegisterAsyncTask(task); }
(1)非同期処理を内包したPageAsyncTaskオブジェクト作成
非同期で行いたい処理を内包するPageAsyncTaskクラスのインスタンスを作成します。PageAsyncTaskクラスのコンストラクタには、Taskオブジェクトを渡します。ここで、async/await構文の出番です。先にMRRS.BLLプロジェクトに定義したビジネスロジックを非同期化しておくことで、async/awaitを使った非同期処理を使って、非同期に実行する処理を記載することができます。
(2)PageAsyncTaskの登録
(1)で作成したPageAsyncTaskオブジェクトを、PageクラスのRegisterAsyncTaskメソッドに渡して呼び出すことで、非同期ページの処理を登録します。あとは登録した処理が自動的にASP.NETに割り当てられたスレッドとは別のスレッドによって行われます。
欲を言えば、イベントハンドラーなどユーザーの入力を受け取るメソッドにasyncをつけることができればよいのですが、現状ではできないようです。
以上で非同期ページを使用する準備は終わりです。実行してみると、非同期ページを導入する前と変わりなく、場所の変更処理が行われることが確認できます。つまり、クライアントサイドからは、非同期であるかどうかを意識することはない、ということです。
まとめ
今回はASP.NET 4.5 Webフォームの新機能の控えめな検証とasync/awaitを用いた非同期ページについて学びました。ポイントをまとめると、次のようになります。
-
控えめな検証は、検証サーバーコントロールによって出力されるJavaScriptが「控えめ」になる
- 控えめな検証が無効の状態では、大量のJavaScriptコードが出力される
- 控えめな検証を有効にすると、data-*属性を利用することによりJavaScriptのコードが抑制される
-
控えめな検証を有効にするには次の手順が必要
- ASP.NET 4.5では既定で有効
- 明示的に有効にするには、Web.configのappSettingsセクションに、キーが"ValidationSettings:UnobtrusiveValidationMode"で値が"WebForms"のエントリを追加する
-
非同期ページは、サーバーサイドの処理をASP.NETとは別のスレッドに移譲し、非同期で処理を行う
- クライアントとサーバー間の処理が非同期になるわけではない
- 目的は大量のリクエストが来た時にASP.NETのワーカースレッドが枯渇することを防ぐこと
-
非同期ページ自体はASP.NET 2.0のころからある
- ASP.NET 4.5では.NET Framework 4.5で導入されたasync/await構文を使って、比較的シンプルに非同期ページを実装できる
-
非同期ページ使用するには次の手順が必要
- Web.configのappSettingsセクションに、キーが"aspnet:UseTaskFriendlySynchronizationContext"で値が"true"のエントリを追加する
- PageクラスのAsyncプロパティをtrueにする(@Pageディレクティブで設定する)
- イベントハンドラーなどで、PageAsyncTaskクラスのオブジェクトを作成する
- PageAsyncTaskのコンストラクタにasync/awaitを用いた非同期処理呼び出しを記載する
- Page.RegisterAsyncTaskメソッドを使い、PageAsyncTaskオブジェクトを登録する
今回でASP.NET 4.5の新機能の紹介は終わりです。次回からは連載の最後として、ASP.NET 4.5ではありませんが、Webフォームの新たな追加機能である「スキャフォールディング」について紹介する予定です。お楽しみに。