5

私はWebFormsで非同期をテストしてきましたが、私の質問は、何かを行う方法ではなく、すでに機能しているものがどのように機能するかについてです。これは私のテストコードです:

protected override void OnPreRender(EventArgs e)
{
    Response.Write("OnPreRender<Br>");
}
protected override void OnPreRenderComplete(EventArgs e)
{
    Response.Write("OnPreRenderComplete<Br>");
}
protected async override void OnLoadComplete(EventArgs e)
{
    Response.Write("OnLoadComplete<br>");
    var t1 = Task.Factory.StartNew(() => {
        System.Threading.Thread.Sleep(2000);
        return 1;
    });

    //This actually does run:
    Response.Write((await t1).ToString());
}

そのため、私のタスクは少し一時停止してから、結果を書き出します。私の質問は、-制御がOnLoadCompleteメソッドから生成されているため、これが機能するとは思わない-ページが実際にレンダリングを終了し、タスクが返される前にクライアントに返されることを期待します。

実際の出力は次のとおりです。

OnLoadComplete
OnPreRender
1OnPreRenderComplete

したがって、OnLoadCompleteメソッドが制御を生成して、OnPreRenderを実行し、制御をOnLoadCompleteに戻すことができることは明らかです。私の予想した結果は、後続のイベントが発生し、ページのスレッドが強制終了されるか、応答が送信された後にタスク後の書き込みが発生するため、「1」が出力されないことでした。上記のことを考えると、10秒間遅らせても、結果がまったく同じであることは驚くことではないと思います。

WebFormエンジンには、ページのライフサイクルの次のフェーズが進む前に、待機可能なものがすべて完了することを保証する配線があると思います。誰かがこれがどのように起こるかを確かに知っていますか?継続が遅すぎることを恐れて、他のイベントの前に完了する必要があるメソッドでasync / awaitを使用することを恐れていますが、それが内部で処理される場合は心配しません。

4

1 に答える 1

11

ASP.NETの場合、.NET4.5のasyncメソッドのみを使用する必要があります。最後にその理由を説明します。

ASP.NETでこれがどのように機能するかについての空白を埋めるのに役立つ記事SynchronizationContextがあります。まず、ASP.NETはかなり前に非同期操作をサポートしていたことに注意してください(.NET 2.0 IIRC)。非同期操作はいくつかの異なる方法で登録できますが、この説明ではに焦点を当てますSynchronizationContext.OperationStarted

ASP.NETは、SynchronizationContext要求ごとにを作成し、登録されているすべての操作が完了するまで(を呼び出すことによりSynchronizationContext.OperationCompleted)、要求が完了していないことを認識します。イベントベースの非同期パターンコンポーネント(など)は、開始および完了時に自動的にBackgroundWorker通知します。SynchronizationContext

同様に、async voidメソッド(新しいタスクベースの非同期パターンSynchronizationContext)は、開始および完了時に自動的に通知します。OnLoadCompleteしたがって、メソッドとしてオーバーライドすると、コンパイラーは、最初と完了時にasync void呼び出すコードを挿入します。OperationStartedOperationCompleted

これまでのところ良好です-ASP.NETは、その要求のすべての非同期操作が完了するまで、要求を存続させることを認識しています。これは、リクエストを処理するスレッドがない場合でも当てはまります。

ここで注意が必要です。.NET4.5より前のASP.NETは、これを要求レベルで処理していました。ASP.NET 4.5では、ライフサイクルパイプラインがよりスマートになり、非同期操作が完了するまでページのライフサイクルが遅れるようになりました。古いASP.NETでは、「pre」ハンドラーはパイプラインのその時点で開始しますが、後で終了するまで終了しない場合があります。async新しいASP.NETは、ライフサイクルに進む前にハンドラーが完了するように、残りのページの実行を遅らせます。

また、ASP.NET 4.5はasync、あるべきではない場所でハンドラーを使用したかどうかを検出し、エラーを通知します。

于 2013-02-07T17:37:29.167 に答える