首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HttpWebResponse ReadAsync超时

HttpWebResponse ReadAsync超时
EN

Stack Overflow用户
提问于 2019-04-16 12:51:53
回答 1查看 569关注 0票数 1

我尝试使用等待/异步读取HttpWebResponse流:

代码语言:javascript
复制
    async static Task testHttpWebClientAsync()        
    {

        string url = "http://localhost/1.txt";
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "GET";
        HttpWebResponse resp = (HttpWebResponse)await req.GetResponseAsync();            
        Stream stream = resp.GetResponseStream();
        stream.ReadTimeout = 10 * 1000;
        byte[] buffer = new byte[1024];
        while (await stream.ReadAsync(buffer, 0, buffer.Length) > 0)                           
        {
            //time out exception never thrown
        }
    }

但是它不起作用,它永远不会在ReadAsync上超时。比较而言,非异步版本可以很好地与相同的本地主机测试服务器工作:

代码语言:javascript
复制
    static void testHttpWebClient()
    {            
        string url = "http://localhost/1.txt";
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "GET";
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        Stream stream = resp.GetResponseStream();
        stream.ReadTimeout = 10 * 1000;
        byte[] buffer = new byte[1024];
        while (stream.Read(buffer, 0, buffer.Length) > 0)
        {
            //time out exception thrown here
        }
    }

上面的代码在控制台应用程序中进行了测试:

代码语言:javascript
复制
    static void Main(string[] args)
    {
        testHttpWebClient();
        MainAsync(args).GetAwaiter().GetResult();
    }
    async static Task MainAsync(string[] args)
    {
        await testHttpWebClientAsync();            
    }

但这与问题无关,实际上,我在WinForms项目中找到了问题,并创建了控制台项目来测试问题。

供参考,测试服务器代码如下所示:

代码语言:javascript
复制
                    int c = 10;
                    byte[] ba = new byte[1024];
                    SendHeader(sHttpVersion, sMimeType,(int) ba.Length*c, " 200 OK", ref mySocket);
                    for (int k = 0; k < c; k++)
                    {
                        //set break point here
                        SendToBrowser(ba, ref mySocket);
                    }

关于这方面有几个类似的话题,但似乎没有一个能解决这个问题。从API设计的角度来看,ReadAsync()没有理由不像Read()那样超时,ReadAsync只需要观察套接字和内部计时器事件,这就是Task.Delay()的工作方式。这与CancellationToken无关,等等,因为我们不需要取消任何东西,甚至ReadAsync也有一个接受CancellationToken的版本。

因此,这个问题既是问题的解决方案,也是为什么ReadAsync不像预期的那样超时。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-18 12:00:03

HttpWebRequest上的异步API(以及WebClient上的异步API,因为它在内部使用HttpWebRequest )内部不使用超时。虽然我无法真正解释其背后的原因,但--这是通过设计实现的。

这是特别明显的)

代码语言:javascript
复制
if (async) {
    m_Connection.BeginMultipleWrite(buffers, m_WriteCallbackDelegate, asyncResult);
}
else {
    SafeSetSocketTimeout(SocketShutdown.Send);
    m_Connection.MultipleWrite(buffers);
}

SafeSetSocketTimeout是负责在基础套接字上设置超时的方法。如您所见,它在异步路径上被故意跳过。读操作也是一样的,但是代码比较复杂,很难显示。

因此,您实际上只有两个解决方案:

  1. 自己实现超时(通常使用一个在.Abort()上调用HttpWebRequest的计时器)
  2. 使用HttpClient代替
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55708619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档