web-dev-qa-db-ja.com

System.Net.WebException:操作がタイムアウトしました

大きな問題があります:一度に200個のオブジェクトを送信し、タイムアウトを回避する必要があります。

while (true)
{

    NameValueCollection data = new NameValueCollection();
    data.Add("mode", nat);

    using (var client = new WebClient())
    {
        byte[] response = client.UploadValues(serverA, data);
        responseData = Encoding.ASCII.GetString(response);

        string[] split = Javab.Split(new[] { '!' },  StringSplitOptions.RemoveEmptyEntries);
        string command = split[0];
        string server = split[1];
        string requestCountStr = split[2];

        switch (command)
        {
            case "check":
                int requestCount = Convert.ToInt32(requestCountStr);

                for (int i = 0; i < requestCount; i++)
                {
                    Uri myUri = new Uri(server);
                    WebRequest request = WebRequest.Create(myUri);
                    request.Timeout = 200000;
                    WebResponse myWebResponse = request.GetResponse();
                }
                break;
        }
    }    
}

これによりエラーが生成されます。

Unhandled Exception: System.Net.WebException: The operation has timed out  
at System.Net.HttpWebRequest.GetResponse()  
at vir_fu.Program.Main(String[] args)

requestCountループはベースコードの外側では正常に機能しますが、プロジェクトに追加するとこのエラーが発生します。 request.Timeout = 200;を設定しようとしましたが、役に立ちませんでした。

26
zimzim

WebResponseオブジェクトを閉じる/破棄します。

33
Joe Chung

それは言うことを意味します。操作の完了に時間がかかりすぎました。

ところで、 WebRequest.Timeout を見ると、タイムアウトが1/5秒に設定されていることがわかります

32
John Saunders

WebClient.UploadValuesを使用する最初のコードサンプルについてはわかりません。先に進むだけでは十分ではありません。周囲のコードをさらに貼り付けていただけますか。 WebRequestコードに関して、ここでは2つのことが行われています。

  1. 応答のヘッダーのみをリクエストしています**。ResponseStreamを開いて(最後まで)読み取り、応答の本文を読み取ることはありません。このため、WebRequestクライアントは接続を開いたままにしておくので、いつでも本文をリクエストすることができます。応答本文を完了するまで読み取り(自動的にストリームを閉じます)、ストリーム(またはWebRequestインスタンス)をクリーンアップして閉じるか、GCが実行するまで待機するまで、接続は開いたままになります。

  2. 2の同じホストへのactive接続のデフォルトの最大量があります。これは、最初の2つの接続を使い果たしてから、決して破棄しないことを意味します。クライアントには、タイムアウトに達する前に次のリクエストを完了する機会が与えられません(ミリ秒単位で、0.2秒に設定しました-デフォルトで十分です)。

応答の本文が必要ない場合(または、何かをアップロードまたはPOSTした直後で、応答を期待していない場合)、ストリームまたはクライアントを閉じて、ストリームを閉じます。

これを修正する最も簡単な方法は、使い捨てオブジェクトでブロックを使用していることを確認することです:

for (int i = 0; i < ops1; i++)
{
    Uri myUri = new Uri(site);
    WebRequest myWebRequest = WebRequest.Create(myUri);
    //myWebRequest.Timeout = 200;
    using (WebResponse myWebResponse = myWebRequest.GetResponse())
    {
        // Do what you want with myWebResponse.Headers.
    } // Your response will be disposed of here
}

別の解決策は、同じホストへの200の同時接続を許可することです。ただし、この操作をマルチスレッド化して複数の同時接続が必要になる場合を除き、これは実際には役立ちません。

 ServicePointManager.DefaultConnectionLimit = 200;

コード内でタイムアウトが発生した場合、最善の方法は、コード外でそのタイムアウトを再作成することです。できない場合、問題はおそらくコードにあります。通常は cURL を使用しますが、単純なGETリクエストの場合は単にWebブラウザーを使用します。

**実際には、HTTPヘッダーを含む応答の最初のデータチャンクと、本文の開始を実際に要求しています。これが、出力ストリームから読み取る前にHTTPヘッダー情報(Content-Encoding、Set-Cookieなど)を読み取ることができる理由です。ストリームを読み取ると、サーバーからさらにデータが取得されます。サーバーへのWebRequestの接続は、このストリームの最後に到達するまで(シークできないので事実上閉じる)、手動で自分で閉じるか、破棄されるまで開いたままになります。 これについてはこちらにあります

26
Matt Brindley

渡したデータの量が原因で、WCFを使用していたときに同じ問題が発生したことを覚えています。私はどこでもタイムアウトを変更したことを覚えていますが、問題は続きました。最後にしたことは、ストリームリクエストとして接続を開くことでした。クライアント側とサーバー側を変更する必要がありましたが、そのように動作します。ストリーム接続であるため、サーバーはストリームが終了するまで読み取りを続けました。

0
Freddy

プロキシの問題がこれを引き起こす可能性があります。 IIS web config put this this

<defaultProxy useDefaultCredentials="true" enabled="true">
          <proxy usesystemdefault="True" />
        </defaultProxy>
0
Blue Clouds