C# HttpWebRequest在第二次调用时超时

C# HttpWebRequest在第二次调用时超时,c#,http,garbage-collection,httpwebrequest,webrequest,C#,Http,Garbage Collection,Httpwebrequest,Webrequest,为什么下面的代码在第二次(以及后续)运行时超时 代码挂起在: using (Stream objStream = request.GetResponse().GetResponseStream()) 然后导致WebException,表示请求已超时 我用WebRequest和HttpWebRequest 编辑:代码似乎在request.GetResponse() 编辑:这篇文章暗示这可能是一个GC问题-->-根据这篇文章,如果Fiddler在后台打开,这个问题会得到缓解 服务器在那里,可用于请

为什么下面的代码在第二次(以及后续)运行时超时

代码挂起在:

using (Stream objStream = request.GetResponse().GetResponseStream())
然后导致WebException,表示请求已超时

我用
WebRequest
HttpWebRequest

编辑:代码似乎在
request.GetResponse()

编辑:这篇文章暗示这可能是一个GC问题-->-根据这篇文章,如果Fiddler在后台打开,这个问题会得到缓解

服务器在那里,可用于请求

    private string GetQLMResponse(string URL)
    {
        HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
        request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
        request.KeepAlive = false;
        request.Timeout = 5000;
        request.Proxy = null;

        // Read stream
        string responseString = String.Empty;
        try
        {
            using (var response = request.GetResponse())
            {
                using (Stream objStream = response.GetResponseStream())
                {
                    using (StreamReader objReader = new StreamReader(objStream))
                    {
                        responseString = objReader.ReadToEnd();
                        objReader.Close();
                    }
                    objStream.Flush();
                    objStream.Close();
                }
                response.Close();
            }
        }
        catch (WebException ex)
        {
            throw new LicenseServerUnavailableException();
        }
        finally
        {
            request.Abort();
            request = null;
            GC.Collect();
        }
        return responseString;
    }
引发的WebException是:

{“操作已超时”} [System.Net.WebException]:{“操作已超时”} 数据:{System.Collections.ListDictionaryInternal} 帮助链接:空 InnerException:null 消息:“操作已超时” 资料来源:“系统” StackTrace:“在C:\Users\jd\SVN\jd\Products\Development\JAD.Licensing\License.cs:第373行的IQX.Licensing.License.GetQLMResponse(字符串URL)处的System.Net.HttpWebRequest.GetResponse()\r\n处” TargetSite:{System.Net.WebResponse GetResponse()}


更新:好,下面的代码现在可以工作了。servicePoint正在将超时设置为接近4分钟。更改请求对象上的
ServicePoint.ConnectionLeaseTimeout
意味着请求现在在5000ms后被销毁。感谢所有人的帮助,也感谢以下两页:


  • 必须正确处理通过
    request.GetReponse()
    获得的
    WebResponse
    。尝试此操作(删除
    request.Abort()
    GC.Collect()
    调用):

    编辑: 由于它仍然不起作用,我建议您使用一个空的windows应用程序来测试它。通过这种方式,您可以隔离app.config问题或每个主机的最大并发调用*(您是否在应用程序中的其他位置使用其他webrequest对象访问此主机;哪些webresponse未正确处理?)

    希望这能解决你的问题,我是出主意了

    • 见Jon Skeet的答案

    正如您所说,在后台运行fiddler可以缓解问题。这是因为小提琴力关闭了所有的反应。根据Sam B的上述帖子,我将确保回复如下:

    using (var wresponse = request.GetResponse())
    {
       using (Stream objStream = wresponse.GetResponseStream())
       {
            // ...
       } 
       wresponse.close();
    }
    
    同样值得将代理设置为null,如下所示:

     request.Proxy = Null;
    

    由于.NET framework将外出搜索代理,除非您明确执行此操作。当fiddler运行时,由于可以直接找到fiddler代理,这种影响将得到缓解。

    在前面的答案之后,我想补充几点。默认情况下,
    HttpWebRequest
    只允许2个到同一主机的连接(这是HTTP 1.1“niceness”)

    是的,它可以被覆盖,不,我不会告诉你如何在这个问题上,你必须问另一个:) 我想你应该看看

    我认为您还没有完全处理好与HttpWebRequest连接的所有资源,因此连接池开始发挥作用,这就是问题所在。我不会尝试对抗每个服务器2个连接的规则,除非你真的必须这么做

    正如上面的一张海报所指出的,在这种情况下,Fiddler对你有点不利

    我会在捕获之后添加一个漂亮的
    finally{}
    子句,并确保如上面的帖子所述,所有流都被刷新、关闭,对请求对象的引用都设置为null


    请告诉我们这是否有帮助。

    我也遇到了同样的问题,我解决了它,确保在创建的每个请求对象上调用
    Abort()
    方法。

    我已将http超时设置为10分钟,它对我有效


    设置为
    timeout=infinite
    花费了更多的时间,我的程序处于挂起模式。

    尽管正确地处理/刷新/关闭了所有内容,但在对服务器的后续请求中遇到了同样的超时问题。尝试刷新您的连接组,为我工作:

    myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);
    

    另外,请确保您没有无意中在应用程序的其他位置创建其他未正确终止/处置的HttpWebRequest/Request对象,因为这会增加服务点中的连接数。

    您是否使用了默认名称为WindowsFormsAppN的测试应用程序?我也遇到了同样的问题,我花了一周时间进行调试,因为它在我的生产代码中起作用,但在我正在构建的简单测试解决方案中却不起作用。最后,我确定此行为对于使用默认解决方案名称而不是正确命名的解决方案是唯一的


    编辑:我发现我的问题与使用BitDefender作为我的AV软件有关。WindowsFormsAppN程序都被阻止了。

    我读了上面标记为“答案”的帖子,但上面的帖子对我来说并不管用。 最后,我使用using标记重写了代码,并添加了一个其他人推荐的CloseConnectionGroup段。最终,代码是这样的:

    System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);
                    webRequest.AllowWriteStreamBuffering = true;
                    webRequest.Timeout = 30000;
                    webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
                    webRequest.ServicePoint.MaxIdleTime = 5000;
    
                    using (System.Net.WebResponse webResponse = webRequest.GetResponse())
                    {
    
                        using (System.IO.Stream stream = webResponse.GetResponseStream())
                        {
                            image = System.Drawing.Image.FromStream(stream);
                        }
                    }
    
                    webRequest.ServicePoint.CloseConnectionGroup(webRequest.ConnectionGroupName);
                    webRequest = null; 
                }
    

    你为什么要用
    gc
    ?这篇文章暗示这可能是垃圾收集问题:哦,谢谢你发布更新。修复了我的问题。感谢发布您的解决方案。今天为我节省了一点时间。谢谢,但这仍然导致相同的问题发生。我已经更新了上面的源代码以反映您的建议。AFAIK WebResponse不实现IDisposable。@JD:是的,它实现了。WebResponse类签名:
    公共抽象类WebResponse:MarshallByRefObject、ISerializable、IDisposable
    ()。但是,WebRequest没有实现IDisposable。@JD:你能发布try-catch中捕获的异常消息吗(使用更新的代码)?@SamB:我已更正-我在IntelisSense中看不到Dispose方法。。。只是假设上面有异常,这很奇怪。我唯一能建议的另一件事是Phil Haak的修正:你的答案对我来说似乎是最不可能的,但它是正确的
    myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);
    
    System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);
                    webRequest.AllowWriteStreamBuffering = true;
                    webRequest.Timeout = 30000;
                    webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
                    webRequest.ServicePoint.MaxIdleTime = 5000;
    
                    using (System.Net.WebResponse webResponse = webRequest.GetResponse())
                    {
    
                        using (System.IO.Stream stream = webResponse.GetResponseStream())
                        {
                            image = System.Drawing.Image.FromStream(stream);
                        }
                    }
    
                    webRequest.ServicePoint.CloseConnectionGroup(webRequest.ConnectionGroupName);
                    webRequest = null; 
                }