web-dev-qa-db-ja.com

HttpResponse.End vs HttpResponse.Close vs HttpResponse.SuppressContent

ASPXページ内で、コードパスに応じて、特定のポイント(エラー状態が原因ではない)で応答を終了し、他に何もストリームに戻されないようにします。だから自然に使われる:

Response.End();

これにより、ThreadAbortExceptionが発生します。これは 設計上 です。

以下は機能しているようですが、 this SO question による正しいアプローチのようには見えません:

Response.Flush();
Response.Close();

それで、これはどうですか?

Response.Flush();
Response.SuppressContent = true

次に、ページを正常に完了させます。

私はThreadAbortExceptionを処理して飲み込むことができましたが、SuppressContentアプローチに問題があるかどうかを知りたいだけですか?

編集:もう少し例を挙げます。 ASPXページがあり、コンテンツタイプをいくつかの可能性の1つに変更できるとします。コンテンツタイプとシナリオに応じて、コードの特定の時点で、これ以上のコンテンツがクライアントに送信されないようにします。 SuppressContentがtrueに設定された後、サーバー側のコードを実行しても問題は発生しないと想定します。他に何もクライアントに送信したくないだけです。

編集2:MyPage.aspx-標準コンテンツ、ヘッダー、フッターなどを含むマスターページがあります。このページは通常のページとしてレンダリングできます。 。また、ダウンロードするXMLドキュメント(例)を書き出すこともできます。 XMLドキュメント(ページの読み込み時に決定)を書き出す場合、出力がクリアされ、content-typeがXMLに設定され、すべてのXMLが書き出されます。その後、通常どおりに残されると、ASPXページの残りのレンダリングが終了します。最後まで付け加えました-それは明らかに必要ではありません/ XMLを壊します。

編集3:現時点では、SuppressContentアプローチを使用しています。この質問を締めくくるために、私は報奨金を上げて、質問を別の言い方で言います:いつすべきかSuppressContentを使用しますか?なぜResponse.Endの代わりに使用するのですか?


Response.Endを使用するときにThreadAbortExceptionを回避する方法を最終的に見つけたので、実際に最終的に得た解決策については、以下に提供する回答を参照してください。私はすでにこの時点で回答を除外していました。


36
AdaTheDev

更新-警告:より良い方法があります。これは使用しないでください。代わりにイーサンの回答を参照してください!

Response.Endを回避する正当な理由があるとは言いません。 ThreadAbortExceptionのコストを回避するために、ページリクエストサイクルを継続させて、不要な追加の作業を行わせるのは適切ではないようです。

ThreadAbortExceptionは、スレッドの実行を停止することを目的とした特殊なタイプの例外です(キャッチされた場合でも自動的に再スローされます)。とはいえ、害を及ぼす可能性のあるシナリオがいくつかあります( ThreadAbortException の最後に追加されたコミュニティコンテンツを参照してください)。

これらのシナリオのいずれかに該当しない限り、Response.Endに固執する必要があります。いくつかの使用法では、SuppressContent&Response.Endを実行することに注意してください。内部のResponse.Flushから発生するものを回避したい場合があると思います。

4
eglasius

これは古い質問であることはわかっていますが、この投稿に遭遇した可能性のある人のために、これを含めています。 Response.Endの使用を確認するためのバグを追跡してきましたが、この質問の1年後にMSDNの投稿を発見しました。これは、「決して使用しないでください。 Response.End」。 IIS7の統合パイプラインを設計したThomas Marquardtが次のように語っています。

Endメソッドも私の「使用しない」リストにあります。リクエストを停止する最良の方法は、HttpApplication.CompleteRequestを呼び出すことです。 Endメソッドが存在するのは、1.0がリリースされたときにclassic ASPと互換性を持たせようとしたためです。ClassicASPには、の処理を終了するResponse.Endメソッドがあります。 ASPスクリプト。この動作を模倣するために、ASP.NETのEndメソッドはThreadAbortExceptionを発生させようとします。これが成功すると、呼び出し元のスレッドは中止され(非常に高価で、パフォーマンスに良くありません)、パイプラインは、EndRequestイベントにジャンプします。ThreadAbortExceptionが成功した場合、もちろん、スレッドがコードを呼び出す前に巻き戻します。したがって、Endを呼び出すと、その後コードは呼び出されません。EndメソッドがはThreadAbortExceptionを発生させることができず、代わりに応答バイトをクライアントにフラッシュしますが、これは同期的に実行されるため、パフォーマンスが大幅に低下します。Endの実行が完了した後のユーザーコードが完了すると、パイプラインはEndRequest通知にジャンプします。 。クライアントへのバイトの書き込みは、特に非常にコストのかかる操作です。クライアントが世界中の半分にあり、56kモデムを使用している場合、非同期でバイトを送信するのが最善です。これは、要求が通常の方法で終了するときに行うことです。同期フラッシュは本当に悪いです。要約すると、Endを使用するべきではありませんが、CompleteRequestを使用することはまったく問題ありません。 Endのドキュメントには、CompleteRequestがEndRequest通知にスキップしてリクエストを完了するためのより良い方法であると記載されているはずです。

から http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn -documentation.aspx

44
Eyeball

最終的に、ThreadAbortExceptionを取得せずにResponse.End()を使用する簡単な解決策を見つけました。

Response.Flush();
Response.End();

元の質問から、コンテンツを応答ストリームに送信した後は、常にResponse.End()だけを試していました。

Response.End()を実行するときにフラッシュされていないコンテンツがある場合、ThreadAbortExceptionが発生するようです。 Endの直前にFlushを実行することにより、ThreadAbortExceptionは実際にはスローされません。

うまく機能しているようです-Response.Endを使用しても、ThreadAbortExceptionはスローされません。

11
AdaTheDev

これは非常に一般的な質問です。そして、ほとんどの場合、Response.End()以外のものを呼び出すのは間違いです。これがMSDNからの End() の説明です:

現在バッファされているすべての出力をクライアントに送信し、ページの実行を停止し、EndRequestイベントを発生させます。

これはまさにあなたがやりたいことのようです。そして最後の部分で、EndRequestイベントが発生することに気付くでしょう。つまり、End()が呼び出された後、End()の前に書き込まれたすべてのデータがクライアントにフラッシュされ、ソケットが閉じられ、リソースが解放され、プログラムは要求の処理をすぐに停止します。

3
Nick Berardi

Response.SuppressContent = trueを呼び出した後、ページがデータベースのレコードに変更を加えた場合はどうなりますか?

1
kͩeͣmͮpͥ ͩ

Flush/SuppressContentアプローチを使用してHttpResponseを反映するときにコードを理解できる限り、フラッシュ後にヘッダーを変更しようとするコードに対して脆弱になります。フラッシュ後にヘッダーを変更すると、HttpExceptionが発生します。

Response.End()を使用して、他に何も応答を妨げることがないことを確実にします。

実行を継続したいがhttpパイプラインを短絡させたい場合は、コンテキストがキャンセル可能な期間にないときにResponse.End()が行うようにResponse.Flush()とHttpContext.Current.ApplicationInstance.CompleteRequest()を使用することを検討してください。

1
Fredrik Haglund

設計戦略は正しいですか?正しいヘッダーが送信されるようにするためにどのような前処理を実行し、スクリプトが目的を達成するまでそれに固執することができますか?

0
Pedro