为什么我有超时的例外,在使用httpwebrequest下载文件时应该如何处理?

时间:2015-02-09 13:12:00

标签: c# .net winforms

这是代码:

HttpWebRequest request;
        int currentIndex = 0;
        void fileDownloadRadar(string uri, string fileName)
        {
            if (splash != null)
            {
                if (!splash.IsDisposed)
                    splash.UpdateProgressBar(0);
            }
            /*_request = WebRequest.Create(uri) as HttpWebRequest;
            _request.CookieContainer = new CookieContainer();
            _request.AllowAutoRedirect = true;
            _responseAsyncResult = _request.BeginGetResponse(ResponseCallback, null);*/
            request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
            request.CookieContainer = new CookieContainer();
            request.AllowAutoRedirect = true;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            long contentLength = response.ContentLength;
            if (response.ContentType == "")
            {
                Logger.Write("ContentType is Empty download was not fine !!!!!");
            }
            if ((response.StatusCode == HttpStatusCode.OK ||
                response.StatusCode == HttpStatusCode.Moved ||
                response.StatusCode == HttpStatusCode.Redirect) &&
                response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
            {
                Logger.Write("ContentType is not empty meaning download is fine");
                using (Stream inputStream = response.GetResponseStream())
                using (Stream outputStream = File.OpenWrite(fileName))
                {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    do
                    {
                        bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                        currentIndex += bytesRead;
                        double percentage = (double)currentIndex / contentLength;
                        if (splash != null)
                        {
                            if (!splash.IsDisposed)
                                splash.UpdateProgressBar((int)(percentage * 100));
                        }
                        outputStream.Write(buffer, 0, bytesRead);
                    } while (bytesRead != 0);
                    if (splash != null)
                    {
                        if (!splash.IsDisposed)
                        {
                            splash.UpdateProgressBar(100);
                        }
                    }
                }

            }
            else
            {
                timer1.Stop();
                timer3.Start();
            }
            if (splash == null)
                FinishWebRequest();
        }

例外是在线:

bytesRead = inputStream.Read(buffer, 0, buffer.Length);

例外是:WebException

操作已超时

我看到当异常发生时,变量bytesRead的值是1360 缓冲区值为4096

System.Net.WebException occurred
  HResult=-2146233079
  Message=The operation has timed out.
  Source=System
  StackTrace:
       at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
       at mws.Form1.fileDownloadRadar(String uri, String fileName) in d:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\Form1.cs:line 914
  InnerException: 

第914行是:

bytesRead = inputStream.Read(buffer, 0, buffer.Length);

也许我应该尝试并抓住某个地方?

我的代码正在下载一个文件,然后计时器正在运行,当计时器计数5分钟它再次下载同一个文件,然后每隔5分钟再次不间断地我调用此方法下载文件。

编辑这是根据答案更改后的代码:

HttpWebRequest request;
        int currentIndex = 0;
        void fileDownloadRadar(string uri, string fileName)
        {
            if (splash != null)
            {
                if (!splash.IsDisposed)
                    splash.UpdateProgressBar(0);
            }
            try
            {
                request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
                request.Timeout = 10000;
                request.CookieContainer = new CookieContainer();
                request.AllowAutoRedirect = true;
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    long contentLength = response.ContentLength;
                    if (response.ContentType == "")
                    {
                        Logger.Write("ContentType is Empty download was not fine !!!!!");
                    }
                    if ((response.StatusCode == HttpStatusCode.OK ||
                        response.StatusCode == HttpStatusCode.Moved ||
                        response.StatusCode == HttpStatusCode.Redirect) &&
                        response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
                    {
                        Logger.Write("ContentType is not empty meaning download is fine");
                        using (Stream inputStream = response.GetResponseStream())
                        using (Stream outputStream = File.OpenWrite(fileName))
                        {
                            byte[] buffer = new byte[4096];
                            int bytesRead;
                            do
                            {
                                bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                                currentIndex += bytesRead;
                                double percentage = (double)currentIndex / contentLength;
                                if (splash != null)
                                {
                                    if (!splash.IsDisposed)
                                        splash.UpdateProgressBar((int)(percentage * 100));
                                }
                                outputStream.Write(buffer, 0, bytesRead);
                            } while (bytesRead != 0);
                            if (splash != null)
                            {
                                if (!splash.IsDisposed)
                                {
                                    splash.UpdateProgressBar(100);
                                }
                            }
                        }

                    }
                    else
                    {
                        timer1.Stop();
                        timer3.Start();
                    }
                    if (splash == null)
                        FinishWebRequest();
                }
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.Timeout)
                {
                    Logger.Write(ex.Status.ToString());
                }
            }
        }

但是它工作了大约一个小时左右并且下载了几次文件后我又得到了异常时间:

操作已超时

这一次就行了:

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())

异常消息:

System.Net.WebException occurred
  HResult=-2146233079
  Message=The operation has timed out
  Source=System
  StackTrace:
       at System.Net.HttpWebRequest.GetResponse()
       at mws.Form1.fileDownloadRadar(String uri, String fileName) in d:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\Form1.cs:line 899
  InnerException:

我更改了响应并使用了使用 还添加:request.Timeout = 10000; 并且还添加了尝试和捕获。

3 个答案:

答案 0 :(得分:3)

您看到的超时是由ServicePointManager 引起的 - 管理ServicePoint 对象集合的类,它为HTTP连接提供连接管理。

简而言之,无论何时创建请求和响应,重要的是在响应对象上调用Close()方法。如果没有,它将阻止释放ServicePoint对象中的任何连接,因此在某些时候,在您发出关键请求数后,不会提供其他请求,您将会遇到超时。

有关更深入的信息,请查看此文章:http://blogs.msdn.com/b/jpsanders/archive/2009/05/20/understanding-maxservicepointidletime-and-defaultconnectionlimit.aspx

HttpWebRequest req = CreateRequest();
HttpWebResponse res = req.GetResponse() as HttpWebResponse;
...
res.Close();  //you should always close the response

编辑:

@Kevin在评论中说,另一个解决方案是将响应包装在using语句中并自动关闭连接:

using(HttpWebResponse res = req.GetResponse() as HttpWebResponse)
{
    ...
}

答案 1 :(得分:3)

第一步是将你的代码放在try..catch

   try
   {
     //code 
   }
   catch (WebException ex)
   {
       if (ex.Status == WebExceptionStatus.Timeout)
       {
           //log your exception
       }
   }

然后使用using块包装Web响应,因为它会自动调用close并释放对象

  using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
      //your code
  }

最后,我在您的代码中看到您尝试使用异步请求,也许您可​​以考虑如果您正在处理大文件来处理超时问题。希望能帮助到你。

答案 2 :(得分:1)

System.Net.WebException: The operation has timed out

这可能适合您的问题,因为它被视为TimeOut异常。 最有用的答案涉及:

https://msdn.microsoft.com/en-us/library/system.net.webrequest.timeout.aspx