22

通常、WebRequest を使用してデータをダウンロードするには、次のようなコードを記述します。

using(WebResponse resp = request.GetResponse())  // WebRequest request...
   using(Stream str = resp.GetResponseStream())  
      ; // do something with the stream str

WebException がスローされた場合、WebException には WebResponse オブジェクトへの参照があり、Dispose が呼び出される場合と呼び出されない場合があります (例外が発生した場所、または応答クラスの実装方法によって異なります) - わかりません。

私の質問は、これにどのように対処するべきかということです。非常に防御的にコーディングし、WebException オブジェクトで応答を破棄することになっています (WebException は IDisposable ではないため、これは少し奇妙です)。または、これを無視して、破棄されたオブジェクトにアクセスする可能性があるか、IDisposable オブジェクトを決して破棄しないことになっていますか? WebException.Response の MSDN ドキュメントに示されている例は、まったく不十分です。

4

6 に答える 6

16

Reflector をざっと見てみたところ、次のように言えます。

  • WebResponseは抽象クラスであり、すべての終了/破棄動作をその派生クラスに委譲します。
  • HttpWebResponseは、ここでほぼ確実に使用している派生クラスであり、その close/dispose メソッドで、実際の応答ストリームの破棄のみに関係しています。クラス状態の残りの部分は、GC の慈悲に任せることができます。

したがって、例外処理に関しては、次の条件を満たしていれば、おそらく安全に処理できます。

  • ブロック内から応答ストリームを読み取る場合WebResponseは、tryブロックで囲みusingます。
  • WebExceptionブロック内から応答ストリームを読み取る場合catchは、それもブロック内に囲みusingます。
  • 廃棄の心配もありませんWebException
于 2009-12-11T11:20:46.107 に答える
3
using (var x = GetObject()) {
     statements;
}

と(ほぼ)同等です

var x = GetObject();
try {
    statements;
}
finally {
     ((IDisposable)x).Dispose();
}

そのため、オブジェクトは常に破棄されます。

これは、あなたの場合、

try {
    using (WebResponse resp = request.GetResponse()) {
        something;
    }
}
catch (WebException ex) {
    DoSomething(ex.Response);
}

ex.Response は、ローカルの resp オブジェクトと同じオブジェクトになります。これは、キャッチ ハンドラーに到達したときに破棄されます。これは、DoSomething が破棄されたオブジェクトを使用していることを意味し、ObjectDisposedException で失敗する可能性があります。

于 2009-12-11T11:09:22.793 に答える
2

usingステートメントがある場合、usingブロックを終了する方法に関係なく、オブジェクトが破棄されることは間違いありません(例外、リターン、または単に関数を介して進行します)。

using ブロックをそのままにしておくと、WebException 内のオブジェクトが既に破棄されていることがわかると思います。

オブジェクトを破棄しても、後でアクセスできないとは限らないことに注意してください。後でメソッドを呼び出そうとすると、それ自体または非常に奇妙な動作の例外が発生する可能性があります (したがって、お勧めしません)。ただし、オブジェクトを破棄しても、オブジェクトの大部分はガベージ コレクターに残されているため、引き続きアクセスできます。Dispose の目的は通常、リソース ハンドル (この場合はアクティブな TCP 接続など) をクリーンアップすることです。これは、パフォーマンス上の理由から、ガベージ コレクターがそれらを見つけるまで現実的に放置することはできません。これについて言及するのは、それが破棄されることと、それへの参照を保持することは相互に排他的ではないことを明確にするためだけです。

于 2009-12-11T11:02:59.560 に答える
0

非常に興味深い質問です (ただし、使用を終了すると WebResponse オブジェクト破棄されることに注意してください)。私の直感では、この破棄された WebResponse オブジェクトへの参照を持っていても、それを使用して「操作」を実行しようとしない限り、それほど重要ではありません。

おそらく、ログを記録する目的でインスタンスの特定のプロパティ (ResponseUri など) にアクセスすることはできますがObjectDisposedException、例外によって保持される全体的な参照は存在しないため、インスタンスを引き続き使用できます。

他の人が何を言っているのか興味があります。

于 2009-12-11T11:05:47.123 に答える
0

EF DB 接続でも同様のケースが発生します。

だから私は実際に接続リストを作成します。

ゲームの最後に、それらすべてをループ処理します。

于 2015-03-05T00:41:07.877 に答える