简体   繁体   English

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

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

This is the code: 这是代码:

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();
        }

The exception is on the line: 唯一的例外是:

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

The exception is: WebException 例外是:WebException

The operation has timed out 操作已超时

I see that when the exception happened the variable bytesRead value is 1360 And buffer values is 4096 我看到发生异常时,变量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: 

Line 914 is: 914行是:

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

Maybe i should put try and catch somewhere ? 也许我应该试着去捉住某个地方?

My code is downloading a file then a timer is running when the timer count 5 minutes it's downloading the same file again and so on over again nonstop every 5 minutes i'm calling this method to download the file. 我的代码正在下载文件,然后当计时器计数5分钟后计时器开始运行,它再次下载同一文件,依此类推,每隔5分钟我不停地调用此方法来下载文件。

EDIT this is my code after changed it according to the answers: 根据答案将其更改后,编辑这是我的代码:

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());
                }
            }
        }

But after it was working fine for maybe an hour or so and downloaded the file few times now i got the exception time out again: 但是在大约一个小时左右可以正常工作并下载了几次文件之后,我又一次遇到了异常超时:

The operation has timed out 操作已超时

This time on the line: 这次上线:

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

And the exception message: 和异常消息:

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:

I changed the response and using the using Also added: request.Timeout = 10000; 我更改了响应,并使用了还添加了:request.Timeout = 10000; And added also try and catch. 并增加了尝试和捕捉。

The timeouts you are seeing are caused by ServicePointManager - class that manages the collection of ServicePoint objects which provides connection management for HTTP connections. 您看到的超时是由ServicePointManager引起的-ServiceClassManager类管理ServicePoint对象的集合,该对象为HTTP连接提供连接管理。

In short, whenever you create a request and the response, the important thing is to call the Close() method on your response object. 简而言之,无论何时创建请求和响应,重要的是在响应对象上调用Close()方法。 If not, it will prevent any of the connections in the ServicePoint object from being freed, so at some point, after you have made the critical number of request, no additional requests can be served and you will experience the timeouts. 否则,它将阻止释放ServicePoint对象中的任何连接,因此,在某些时候,提出了关键数量的请求后,将无法再处理其他请求,并且您将经历超时。

For more in depth information check out this article: http://blogs.msdn.com/b/jpsanders/archive/2009/05/20/understanding-maxservicepointidletime-and-defaultconnectionlimit.aspx 有关更多详细信息,请查看本文: 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

EDIT: 编辑:

as @Kevin said in the comment, another solution would be to wrap the response in a using statement and that would automatically close the connection: 正如@Kevin在评论中所说,另一种解决方案是将响应包装在using语句中,这将自动关闭连接:

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

The first step is to put your code inside try..catch 第一步是将代码放入try..catch中

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

Then wrap the web response with a using block because it automatically call close and also dispose the object 然后将Web响应包装在using块中,因为它会自动调用close并处理该对象

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

Lastly, I see in your code you have attempted to use asynchronous request, maybe you can consider that if you're dealing with huge files to deal with a timeout issue. 最后,我在您的代码中看到您尝试使用异步请求,也许您可​​以考虑一下,如果要处理大型文件以解决超时问题。 Hope it helps. 希望能帮助到你。

System.Net.WebException: The operation has timed out System.Net.WebException:操作已超时

This may fit for your problem, as it is regarded to a TimeOut Exception. 这可能适合您的问题,因为它被视为超时异常。 The most helpful answer relates to: 最有用的答案涉及:

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

暂无
暂无

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

相关问题 为什么我会出现内存不足异常,应该如何避免? - Why i'm getting out of memory exception and how should i avoid it? 为什么我的内存异常? - Why i'm getting out of memory exception? 使用System时,我仍然收到null异常。管理无法弄清原因 - I'm still getting null exception when using the System.Management can't figure out why 为什么我第二次开始下载ProgressBar值为104时出现异常? - Why i'm getting exception that the progressBar value is 104 on the second time i start download? 我正在尝试使用 FileStream 创建一个文件,但为什么会出现异常? - I'm trying to create a file using FileStream but getting an exception why? 为什么在使用backgroundworker时出现InvalidOperationException异常? - Why i'm getting exception InvalidOperationException when using backgroundworker? 为什么当我单击按钮取消Web客户端的下载进度时却出现异常? - Why when I click on the button to cancel the web client download progress I'm getting exception? 为什么我使用的ffmpeg和管道来创建实时视频文件时遇到奇怪的视频文件? - Why i'm getting strange video file when using ffmpeg and pipes to create video file in real time? 文件下载完成后,我怎么知道使用httpwebrequest和webresponse? - How do i know using httpwebrequest and webresponse when a file download is completed? 我正在使用backgroundworker并得到:InvalidOperationException:跨线程操作无效-我应该如何处理? - I'm using backgroundworker and getting: InvalidOperationException: Cross-thread operation not valid - how should I handle it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM