繁体   English   中英

为什么我收到超时异常,使用httpwebrequest下载文件时应如何处理?

[英]Why i'm getting time out exception and how should i handle this when using httpwebrequest to download a file?

这是代码:

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; 并增加了尝试和捕捉。

您看到的超时是由ServicePointManager引起的-ServiceClassManager类管理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)
{
    ...
}

第一步是将代码放入try..catch中

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

然后将Web响应包装在using块中,因为它会自动调用close并处理该对象

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

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

System.Net.WebException:操作已超时

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

https://msdn.microsoft.com/zh-CN/library/system.net.webrequest.timeout.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM