并发时WebRequest同一个网址只能访问两次的解决办法——附C#源码

一、问题描述

有时候我们会用HttpWebRequest的方式向某个网站发送请求,方法如下:

            WebRequest request1 = HttpWebRequest.Create("https://blog.csdn.net/");
            request1.BeginGetResponse(ar =>
            {
                var response1 = request1.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get1");

            }, null);

但作者发现,在并发情况下(甚至不需要高并发),如果短时间内向同一个网站发送两次以上的请求,第三次之后就不会再有返回数据了。目前发现这种情况只存在于访问同一网址的时候,若每次访问的网址不同,则不会出现这种情况。

比如我们按照下面的方式写,就会发现程序只有前两个链接有返回值:

public static void WebRequest()
        {
            WebRequest request1 = HttpWebRequest.Create("https://blog.csdn.net/");
            request1.BeginGetResponse(ar =>
            {
                var response1 = request1.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get1");

            }, null);

            WebRequest request2 = HttpWebRequest.Create("https://blog.csdn.net/");
            request2.BeginGetResponse(ar =>
            {
                var response2 = request2.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get2");

            }, null);

            WebRequest request3 = HttpWebRequest.Create("https://blog.csdn.net/");
            request3.BeginGetResponse(ar =>
            {
                var response3 = request3.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get3");

            }, null);

        }

运行结果如下:

很显然,request3因为某些问题发生了阻塞,这个阻塞的原因并不是没有将请求消息发送出去,而是发送出去的消息没有返回,从而阻塞在了等待的消息的阶段。

二、解决办法

那要如何解决这个问题呢?就需要用到Abort()这个方法了。

我们加上Abort()这个方法试试,代码如下:

public static void WebRequest()
        {
            WebRequest request1 = HttpWebRequest.Create("https://blog.csdn.net/");
            request1.BeginGetResponse(ar =>
            {
                var response1 = request1.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get1");

            }, null);

            WebRequest request2 = HttpWebRequest.Create("https://blog.csdn.net/");
            request2.BeginGetResponse(ar =>
            {
                var response2 = request2.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get2");

            }, null);

            //不能立刻终止WebRequest,要等待WebRequest执行完成之后终止
            Thread.Sleep(2000);
            request1.Abort();

            WebRequest request3 = HttpWebRequest.Create("https://blog.csdn.net/");
            request3.BeginGetResponse(ar =>
            {
                var response3 = request3.EndGetResponse(ar);
                Console.WriteLine(DateTime.Now + ": Response Get3");

            }, null);

        }

来看看运行结果:

并发时WebRequest同一个网址只能访问两次的解决办法——附C#源码_第1张图片

OK,阻塞的问题已经解决了。

虽然还不清楚是什么机制,可能是因为网络协议的原因,还是因为部分网站设置访问限制的原因,亦或是其他原因。在并发情况下,一个WebRequest对同一个网址访问次数不能超过两次。否则需要用WebRequest.Abort()方法终止掉当前的WebRequest,而后才能继续请求。

GitHub源码地址:https://github.com/yangwohenmai/TEST/tree/master/HttpWebRequestAbort

三、后记

如果我们想做高并发的话,结合之前多线程的文章,我们可以用线程同步Task.WaitAll() + WebRequest.Abort()的方法解,决这个问题

 

你可能感兴趣的:(小技术_C#)