2013-02-07 7 views
5

私はWebFormsで非同期をテストしていましたが、私の質問は何かをする方法ではなく、すでに動作しているものがうまくいくかどうかということです。これは私のテストコードです:WebFormsのAsync/Await - ページのライフサイクルが終了する前に継続をどのように実行しますか?

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 

だから、OnPreRenderを実行し、OnLoadCompleteに戻って制御できるようにOnLoadComplete方法は、コントロールをもたらしたことは明らかです。私の期待される結果は、 "1"は決して印刷されませんでした。これは、後続のイベントが発生し、応答が送信された後にページのスレッドが強制終了されるか、ポストタスクの書き込みが発生するためです。私は、上記を考えれば、たとえ10秒間遅れても、結果はまったく同じであることは驚くことではないと思います。

WebFormエンジンには、ページのライフサイクルの次の段階が進む前に待ち時間が完了することを保証する配線があると仮定します。誰がこれがどう起こるかを知っていますか?私は、継続が遅すぎることを恐れて他のイベントよりも前に完了する必要があるメソッドで非同期/待機を使用することを恐れていますが、内部的に処理される場合は心配しません。

答えて

11

ASP.NETの場合、.NET 4.5ではasyncのメソッドしか使用しないでください。私は最後に理由を説明します。

私はan article on SynchronizationContextを持っています。これは、ASP.NETでのこの動作の仕方を記入するのに役立ちます。まず、ASP.NETが長い時間前に非同期操作をサポートしていたことに注目してください(.NET 2.0 IIRC)。非同期操作を登録する方法はいくつかありますが、この説明ではSynchronizationContext.OperationStartedに焦点を当てます。

ASP.NETは要求ごとにSynchronizationContextを作成し、登録されたすべての操作が完了するまで(SynchronizationContext.OperationCompletedを呼び出して)要求が完了していないことを認識します。 Event-based asynchronous pattern componentsBackgroundWorkerなど)は、開始時と完了時に自動的にSynchronizationContextに通知します。

同様に、async voidのメソッド(新しいtask-based asynchronous pattern)は、開始時および完了時に自動的にSynchronizationContextに通知します。だからOnLoadCompleteasync voidメソッドとして上書きすると、コンパイラはコードの最後にOperationStartedOperationCompletedを呼び出してコードを挿入します。

これまでのところ、ASP.NETは、その要求に対するすべての非同期操作が完了するまで要求を有効に保つことができます。これは、要求を処理しているスレッドがなくても当てはまります。

警告:.NET 4.5より前の警告はの要求レベルでこれを処理します。 ASP.NET 4.5では、ライフサイクルパイプラインがよりスマートになり、非同期操作が完了するまでページのライフサイクルが遅れることになりました。古いASP.NETでは、パイプラインのその時点でになりますが、後で完了することはありません。新しいASP.NETは、残りのページの実行を遅延させて、asyncハンドラが完了してからライフサイクルに移行するようにします。

また、ASP.NET 4.5では、asyncハンドラを使用してはいけないと判断し、エラーを通知します。

関連する問題