web-dev-qa-db-ja.com

非同期にできるASP.NETライフサイクルイベントはどれですか?

カスタムASP.NETコントロールを作成し、非同期のLoadイベントハンドラーを持つように更新しました。今、私はこのエラーを得ています:

現在、非同期操作を開始できません。非同期操作は、非同期ハンドラーまたはモジュール内、またはページライフサイクルの特定のイベント中にのみ開始できます。ページの実行中にこの例外が発生した場合は、ページに<%@ Page Async = "true"%>のマークが付いていることを確認してください。

ページdoesには<%@ Page Async="true" %>タグはすでにあります。したがって、コントロールには非同期のロードイベントハンドラーを含めることはできません。

ASP.NET Webフォームのライフサイクルで、非同期にすることが許可されているイベントの包括的なリストはどこにありますか?

27
Andrew Arnott

ASP.NETチームのダミアンエドワーズはこの答えを出しました:

Webフォームの非同期voidイベントハンドラーは、ご存じのように特定のイベントでのみサポートされていますが、実際には単純なタスクのみを目的としています。実際の複雑さの非同期作業にはPageAsyncTaskを使用することをお勧めします。

ASP.NETチームのLevi Broderickがこの答えを出しました。

Webアプリケーションの非同期イベントは、本質的に奇妙なものです。 Async voidは、Fire and Forgetプログラミングモデル用です。これは、Windows UIアプリケーションで機能します。これは、アプリケーションがOSによって強制終了されるまで待機するため、非同期コールバックが実行されるたびに、対話できるUIスレッドが存在することが保証されます。 Webアプリケーションでは、要求は本質的に一時的であるため、このモデルはばらばらになります。リクエストの完了後に非同期コールバックが実行された場合、コールバックがやり取りする必要のあるデータ構造がまだ良好な状態にあるという保証はありません。したがって、なぜファイアアンドフォーゲット(および非同期のvoid)が本質的にWebアプリケーションでは悪い考えです。

とは言っても、Page_Loadのような非常に単純なものを機能させるために体操を行っていますが、これをサポートするコードは非常に複雑であり、基本的なシナリオ以外では十分にテストされていません。したがって、信頼性が必要な場合は、RegisterAsyncTaskを使用します。

だから私の質問への答えは「それは間違った質問だ」と思います。

正しい質問は、「ASP.NET Webフォームアプリケーションでどのように非同期にする必要があるか」です。そして答えは、このスニペットをaspx分離コードファイル内に挿入することです。

this.RegisterAsyncTask(new PageAsyncTask(async cancellationToken => {
    var result = await SomeOperationAsync(cancellationToken);
    // do something with result.
}));

これと同じトリックがASP.NETカスタムコントロール内でも機能します。代わりにthis.Page.RegisterAsyncTaskを使用してください。

28
Andrew Arnott

このページでは、非同期ページのライフサイクルイベント処理がASP.NET 2.0の同期ページのそれとどのように異なるかを説明します(図2は特に役立ちます)。

邪悪なコード:ASP.NET 2.0の非同期ページ

また、SO使用に関する質問(同じエラーメッセージについて話している))も見つかる場合があります。

asyncキーワードとTaskSchedulerの選択

1
Lokerim