非同期 ASP.NET Page

TechEd 2008 NorthAmerica で聞いてきたことのメモ。HttpHandler でなく Page に対して非同期実行を指示する方法。

Programming Microsoft ASP.NET 2.0 Applications–Advanced Topics にも書いてあるようだが本の中は今のところ未確認。

参考サイト Async Pages API 

AddOnPrerenderCompleteAsync による実装方法:

  • 各aspxファイルの先頭 @Page のところで Async="true" を追加して非同期実行を指示する
  • AddOnPrerenderCompleteAsync を使って非同期実行をすることができるが、複数回 AddOnPrerenderCompleteAsync を呼び出して登録した場合、それぞれの登録されたメソッドは順番に呼ばれる。(同時実行ではない)
  • 同時実行するためには、IAsyncResult を自分で実装する

PageAsyncTask + RegisterAsyncTask による実装方法

  • この方法であれば同時実行を指示する引数がある
  • TimeOut時のイベントを指定することもできる。TimeOut時間の指定は @Pages AsyncTimeout プロパティ
  • ExecuteRegisteredAsyncTasks メソッドを利用して強制的に登録されたタスクを実行できるが、この場合同期実行となり実行完了まで待たされる
  • EndThread はページの最初の実行とは別のスレッドがスレッドプールから割り当てられる。HttpContext.Current が null になるので注意。あらかじめコンテキストへのポインタはインスタンス内に確保しておくべき。また、さらに impersonate が終了してASP.NETワーカープロセスのidentityで動作しているので注意。
  • 非同期実行スレッド内での例外発生については、そのままでは例外情報を画面表示等に返せないので、インスタンス内にポインタを代入して親スレッド側で対処する方がよい。
  • 同時実行させる場合、多数のアクセスに対して非同期実行スレッドが無限に増やせるわけではないので、ASP.NETのページ処理とは別に自前でスレッドプールを実装する必要があるだろう。

(追記)一番重要なことを書き忘れた

  • 非同期実行はASP.NETライフサイクルの中で、PreRenderの後、PreRenderCompleteの前に差し込まれる(ExecuteRegisteredAsyncTasksを使わなかった場合)

(さらに追記 7/3)Advanced Topics を読んだ時の感想 を2年前に自分で書いている。なんということだ。

TechEd 2008 NA では使いどころについても解説してくれていたのでそれも書いておかないと

  1. 「外部のサービスからデータを取得するのに時間がかかる場合」
  2. 「多数のアクセスがあって ASP.NET スレッドプールが枯渇してしまう」という状況
  3. PreRender ステージの時点でASP.NET スレッドプールに一度スレッドを戻すことができるようになり、結果として多数のアクセスを処理できるようになる
  4. とはいえその外部のサービスへのアクセスをするスレッドを管理しなくていいわけではない。

2年前の日記にあるように、AJAXが使える状況であれば時間のかかる処理の部分はAJAXを使って解決した方が簡単だと思う。(サーバ側は非同期HttpHandlerでJSON返す方向で)

なのでAJAXが使えない環境である携帯サイトでは検討の価値があるかもしれない。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。