web-dev-qa-db-ja.com

2回目の呼び出しでHttpWebRequestがタイムアウトする

次のコードが実行される2回目(およびそれ以降)にタイムアウトするのはなぜですか?

コードは次の場所でハングします。

_using (Stream objStream = request.GetResponse().GetResponseStream())
_

そして、リクエストがタイムアウトしたことを伝えるWebExceptionを引き起こします。

私はWebRequestHttpWebRequestでこれを試しました

編集:コードはrequest.GetResponse()で倒れているようです

編集:この投稿は、GCの問題である可能性があることを示唆しています-> http://www.vbforums.com/showthread.php?t=61004 -この投稿により、Fiddlerがバックグラウンドで開きます。

サーバーはそこにあり、リクエストに使用できます。

_    private string GetQLMResponse(string URL)
    {
        HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
        request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
        request.KeepAlive = false;
        request.Timeout = 5000;
        request.Proxy = null;

        // Read stream
        string responseString = String.Empty;
        try
        {
            using (var response = request.GetResponse())
            {
                using (Stream objStream = response.GetResponseStream())
                {
                    using (StreamReader objReader = new StreamReader(objStream))
                    {
                        responseString = objReader.ReadToEnd();
                        objReader.Close();
                    }
                    objStream.Flush();
                    objStream.Close();
                }
                response.Close();
            }
        }
        catch (WebException ex)
        {
            throw new LicenseServerUnavailableException();
        }
        finally
        {
            request.Abort();
            request = null;
            GC.Collect();
        }
        return responseString;
    }
_

スローされるWebExceptionは次のとおりです。

{「操作がタイムアウトしました」} [System.Net.WebException]:{「操作がタイムアウトしました」}データ:{System.Collections.ListDictionaryInternal} HelpLink:null InnerException:nullメッセージ:「操作がタイムアウトしました」ソース: "System" StackTrace: "System.Net.HttpWebRequest.GetResponse()\ r\n at IQX.Licensing.License.GetQLMResponse(String URL)in C:\ Users\jd\SVN\jd\Products\Development\JAD.Licensing\JAD.Licensing\License.cs:line 373 "TargetSite:{System.Net.WebResponse GetResponse()}


更新:OKこれで、次のコードが機能するようになりました。 servicePointは、タイムアウトを4分近くに設定していました。要求オブジェクトで_ServicePoint.ConnectionLeaseTimeout_を変更すると、5000ms後に要求が破棄されるようになります。あなたの助けとこれらの2ページに感謝します:

  1. http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx
  2. http://msdn.Microsoft.com/en-us/library/6hszazfz(v = VS.80).aspx

    _private string GetQLMResponse(string URL)
    {
        HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
        request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
        request.KeepAlive = false;
        request.Timeout = 5000;
        request.Proxy = null;
    
        request.ServicePoint.ConnectionLeaseTimeout = 5000;
        request.ServicePoint.MaxIdleTime = 5000;
    
        // Read stream
        string responseString = String.Empty;
        try
        {
            using (WebResponse response = request.GetResponse())
            {
                using (Stream objStream = response.GetResponseStream())
                {
                    using (StreamReader objReader = new StreamReader(objStream))
                    {
                        responseString = objReader.ReadToEnd();
                        objReader.Close();
                    }
                    objStream.Flush();
                    objStream.Close();
                }
                response.Close();
            }
        }
        catch (WebException ex)
        {
            throw new LicenseServerUnavailableException();
        }
        finally
        {
            request.Abort();
        }
        return responseString;
    }
    _
43
Darbio

前の回答に続いて、さらに2つ追加したかったのです。デフォルトでは、HttpWebRequestは同じホストへの接続を2つだけ許可します(これはHTTP 1.1の「ナイスネス」です)。

はい、オーバーライドできます。いいえ、この質問でどのように伝えるかはわかりません。別の質問をする必要があります:) this post をご覧ください。

HttpWebRequestに接続されているすべてのリソースをまだ完全に破棄しているわけではないと思うので、接続プーリングが関係してくるのが問題です。本当に必要な場合を除き、サーバールールごとに2つの接続と戦うつもりはありません。

上記のポスターの1つが指摘したように、この場合、フィドラーはあなたにちょっとした不満を与えています。

キャッチの後にNice finally {}句を追加し、上記の投稿ノートのように、すべてのストリームがフラッシュされ、閉じられ、リクエストオブジェクトへの参照がnullに設定されることを確認します。

これが役立つかどうかをお知らせください。

27
dawebber

request.GetReponse()で取得したWebResponseは適切に破棄する必要があります。これを試してください(request.Abort()およびGC.Collect()呼び出しを削除します):

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   }
}

Edit:それでも動作しないので、空のWindowsアプリケーションでテストすることをお勧めします。この方法で、app.configの問題またはホストごとの最大同時呼び出し*を分離できます(このホストに対するアプリケーションの別の場所で他のwebrequestオブジェクトを使用していますか?適切に処理されないwebresponseはありますか?)。

これがあなたの問題を解決することを願っています、私はアイデアがありません!

  • Jon Skeetの答え here をご覧ください。
21
Sam B

あなたが述べたように、バックグラウンドでフィドラーを実行すると、問題が軽減されます。これは、バイオリンフォースが応答を閉じるためです。 Sam Bからの上記の投稿を拡張すると、応答が次のように閉じられるようになります。

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   } 
   wresponse.close();
}

また、次のようにプロキシをnullに設定する価値があります。

 request.Proxy = Null;

.NETフレームワークは、明示的にこれを行わない限り、プロキシの検索を行うため。フィドラーが実行されている場合、フィドラープロキシが直接検出されるため、この効果は軽減されます。

8
Sean Hunter

すべてを適切に破棄/フラッシュ/閉じるにもかかわらず、サーバーへの後続のリクエストでタイムアウトが発生するという同じ問題に遭遇しました。接続グループをフラッシュしてみてください、私のために働いた:

myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);

また、サービスポイントの接続数が増加するため、アプリケーションの別の場所に適切に終了/破棄されていない他のHttpWebRequest/Requestオブジェクトを誤って作成しないようにしてください。

5
rdltrr

私は同じ問題を抱えており、作成された各リクエストオブジェクトでAbort()メソッドを確実に呼び出すように解決しました。

1
Paul Schneider

おそらく、WindowsFormsAppという既定の名前のテストアプリを使用していました[〜#〜] n [〜#〜]?私が作成していた簡単なテストソリューションではなく、実稼働コードで機能したため、1週間のデバッグと同じ問題がありました。最終的に、この動作は、適切な名前のソリューションではなく、デフォルトのソリューション名を使用することに固有であると判断しました。

編集:私の問題は、AVソフトウェアとしてBitDefenderを使用することに関連していることがわかりました。 WindowsFormsApp [〜#〜] n [〜#〜]プログラムはすべてブロックされました。

0
oldSchool