web-dev-qa-db-ja.com

HttpWebRequestタイムアウト処理

とても簡単な質問があります。 HTTP POSTを使用してサーバーにファイルをアップロードしています。問題は、接続タイムアウトを特別に処理し、タイムアウトが発生した後にサーバーを再現するために待機アルゴリズムを少し追加する必要があることです。

私のコードはとても簡単です:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("SomeURI");
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.KeepAlive = true;
request.Accept = "*/*";
request.Timeout = 300000;
request.AllowWriteStreamBuffering = false;

try
{
      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
      {
            WebHeaderCollection headers = response.Headers;    
            using (Stream Answer = response.GetResponseStream())
            {
                // Handle.
            }
      }
}
catch (WebException e)
{
    if (Timeout_exception)
    {
       //Handle timeout exception
    }
}

私たちの関心事ではないので、ファイルの読み取りコードは省略しました。ここで、WebExceptionがスローされたら、例外をフィルタリングして、実際にタイムアウト例外であるかどうかを確認する必要があります。例外メッセージと比較することを考えましたが、問題のアプリケーションは商用アプリであり、メッセージが言語によって異なるため、これが正しい方法であるかどうかはわかりません。そして、私はどんなメッセージを探していなければなりません。

助言がありますか?

24
Zaid Amir

WebException.StatusWebExceptionStatus enumにはTimeoutフラグがあります。

try
{
   using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
   {
      WebHeaderCollection headers = response.Headers;    
      using (Stream answer = response.GetResponseStream())
      {
          // Do stuff
      }
   }
}
catch (WebException e)
{
   if (e.Status == WebExceptionStatus.Timeout)
   {
      // Handle timeout exception
   }
   else throw;
}

ここでは、C#6例外フィルターを使用すると便利です。

try
{
    var request = WebRequest.Create("http://www.google.com");
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        WebHeaderCollection headers = response.Headers;
        using (Stream answer = response.GetResponseStream())
        {
            // Do stuff
        }
    }
}
catch (WebException e) when (e.Status == WebExceptionStatus.Timeout)
{
    // If we got here, it was a timeout exception.
}
41
Yuval Itzchakov

Yuvalの答えは非常に直接的なヒットですが、ステータスコードでターゲットにしたい場合は同じ状況で経験したので、私が試したバージョンは次のとおりです:

catch (WebException ex)
            {
                var hwr = (HttpWebResponse)ex.Response;
                if (hwr != null)
                {
                    var responseex = hwr.StatusCode;
                    int statcode = (int)responseex;
                    if (statcode == 404)
                    {
                        Utility.Instance.log(logPath, "The file might not be availble yet at the moment. Please try again later or contact your system administrator.", true);
                    }
                    if (statcode == 401)
                    {
                        Utility.Instance.log(logPath, "Username and Password do not match.", true);
                    }
                    if (statcode == 408)
                    {
                        Utility.Instance.log(logPath, "The operation has timed out", true);
                    }
                }
                else
                {
                    Utility.Instance.log(logPath, ex + ". Please contact your administrator.", true);//Or you can do a different thing here
                }
            }
0
OneLazy