关于HttpWebRequest的问题,困扰我几个月了

threadroc 2014-03-19 09:49:08
我用HttpWebRequest访问网页,设置了代理,如果代理不可用的话,会卡20秒才返回.
即使设置以下两个方法分别为1秒,照样还是20秒才返回,
httpWebRequest.Timeout和httpWebRequest.ReadWriteTimeout两个方法;
有点浪费时间,困扰很久了,一设置代理,这两个方法直接就失效了,
另外异步不行的,不能设置Keep-Alive.
不知道各路大侠有没有什么方法能解决此问题的,实在不行推荐款其他插件也行啊,
谢谢各位大大.
...全文
828 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
threadroc 2014-03-22
  • 打赏
  • 举报
回复
引用 12 楼 mikecheers 的回复:
代理的不稳定性是很难预判的,至少我还没有找到很好的办法,往往尝试连接代理服务器会花费很长的时间. 如果是想快速响应,并跳过无效代理,可以使用线程,通过ManualResetEvent的Wait方法阻塞等待,判断超时.如果超时,可以切换别的代理.当然,这个等待超时时间可以包括连接+等待回复的时间. 我的处理方式是建立一个大的代理服务器地址列表, 给每个代理服务器地址分配一个权重. 每次取随机数*权重,排序,用值最大的代理服务器地址. 权重的初始值是一样的, 再通过成功连接数,失败连接数,平均连接花费时间等,动态调整权重.
谢谢这位大大的思路,我现在用HttpClient已经可以准确设置超时了,并且是4.0环境,现在遇到的问题是,1,2个线程没问题,开多了线程,比如说600线程,直接就报异常,一个网页都不能正常访问,貌似这HttpClient不能太多线程,怎么破
MikeCheers 2014-03-22
  • 打赏
  • 举报
回复
我承认我还是没有耐心把你的代码看完 同学,贴代码前,把不比要的去掉,几个关键点加点注释,标记一下问题的位置。 不要莫名其妙的出来个变量,都不知道是什么,看得费劲。 既然你已经找到解决方案了,就这样吧。
hard_learner 2014-03-22
  • 打赏
  • 举报
回复
引用 12 楼 mikecheers 的回复:
代理的不稳定性是很难预判的,至少我还没有找到很好的办法,往往尝试连接代理服务器会花费很长的时间. 如果是想快速响应,并跳过无效代理,可以使用线程,通过ManualResetEvent的Wait方法阻塞等待,判断超时.如果超时,可以切换别的代理.当然,这个等待超时时间可以包括连接+等待回复的时间. 我的处理方式是建立一个大的代理服务器地址列表, 给每个代理服务器地址分配一个权重. 每次取随机数*权重,排序,用值最大的代理服务器地址. 权重的初始值是一样的, 再通过成功连接数,失败连接数,平均连接花费时间等,动态调整权重.
这个思路好,呵呵
threadroc 2014-03-22
  • 打赏
  • 举报
回复
我想我找到原因了,是委托的原因

for (int i = 0; i < RocVariableClass.threadAmount; i++)
                {
                    //delegateFun dgc = new delegateFun(startThread);
                    ////listdgc.Add(dgc);//把委托代理添加到集合?
                    //IAsyncResult ir = dgc.BeginInvoke(dgcCallBack, dgc);//启动委托,异步可以用此
                    Thread threadClass = new Thread(()=>startThread());
                    threadClass.IsBackground = true;
                    threadClass.Start();
                    RocVariableClass.threadCount++;//线程数+1;
                    if (labelThreadCount != null)
                    {
                        setLabelThreadCountText();
                    }
                }
我把委托启动换成线程启动就好用了,不知道为何....
threadroc 2014-03-22
  • 打赏
  • 举报
回复
现在的问题是,确定是超时引发的异常,需要解决的是怎么捕获到这异常,线程少的时候可以捕获到,线程多了就捕获不到了
threadroc 2014-03-22
  • 打赏
  • 举报
回复
再详细说一下我遇到的问题
就是我引用了4.0的的system.net.http,写了个工具类,代码如下:

class HttpClientClass
{
//public ManualResetEvent allDone = new ManualResetEvent(false);
public CookieContainer cc = null;
public Encoding encoding = Encoding.GetEncoding("utf-8");//默认utf-8
public string accept = "text/html, application/xhtml+xml, */*";
public string referer = null;
public string accept_language = "en-US";//zh-CN
public string user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
public string content_type = "application/x-www-form-urlencoded";
public string accept_encoding = "gzip, deflate";
public string connection = "Keep-Alive";
public int timeout = 10000;
private ExceptionClass exceptionClass = new ExceptionClass();
public string getHtml(string url, CookieContainer cc)
{

HttpClient client = null;
HttpClientHandler handler = null;
HttpResponseMessage response = null;
HttpContent httpContent = null;
try
{
handler = new HttpClientHandler()
{
//Proxy = new WebProxy("114.241.183.23:18186"),
//UseProxy = true,
CookieContainer = cc,
UseCookies = true,
AllowAutoRedirect = true,
};
// ... Use HttpClient.
client = new HttpClient(handler);
#region 添加head
client.DefaultRequestHeaders.Add("Accept", accept);
if (referer != null)
{
client.DefaultRequestHeaders.Add("Referer", referer);
}
client.DefaultRequestHeaders.Add("Accept-Language", accept_language);
client.DefaultRequestHeaders.Add("User-Agent", user_agent);
//client.DefaultRequestHeaders.Add("Connection", connection);
//client.DefaultRequestHeaders.Add("Content-type", content_type);
//client.DefaultRequestHeaders.Add("Accept-Encoding",accept_encoding);
#endregion

client.Timeout = new TimeSpan(timeout * 10000);
//var byteArray = Encoding.ASCII.GetBytes("username:password1234");
//client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
MessageBox.Show("1");
try
{
response = client.GetAsync(url).Result;//这一句的问题
}
catch
{
}

MessageBox.Show("2");
httpContent = response.Content;

// ... Check Status Code
//Console.WriteLine("Response StatusCode: " + (int)response.StatusCode);//输出状态码;

// ... Read the string.
string result =httpContent.ReadAsStringAsync().Result;
// ... Display the result.
return result;//有可能返回null;
}
catch (AggregateException)//超时引发的异常
{
Console.WriteLine("threadroc:AggregateException");
return null;
}
catch(Exception e)
{
MessageBox.Show(exceptionClass.getExceptionMsg("HttpClientClass",e));
return null;
}
finally
{
if (client != null)
{
client.Dispose();
}
if (handler != null)
{
handler.Dispose();
}
if (response != null)
{
response.Dispose();
}
if (httpContent != null)
{
httpContent.Dispose();
}
}
}
}


response = client.GetAsync(url).Result;//这一句,异常捕获不到,开1,2个线程能正常运行,我如果设置超过100线程,直接就报错,
具体什么错误看不太懂,直接上图把,另外我调用此方法的时候线程是锁定的,当时只有1个线程在调用此方法,其他线程全在锁定外面还没进来,但是居然报错了,有点纳闷了,忘大神解决,谢谢,如果能解决掉的大神可以给100R红包以作酬谢
上图:
MikeCheers 2014-03-22
  • 打赏
  • 举报
回复
引用 14 楼 threadroc 的回复:
... ... 谢谢这位大大的思路,我现在用HttpClient已经可以准确设置超时了,并且是4.0环境,现在遇到的问题是,1,2个线程没问题,开多了线程,比如说600线程,直接就报异常,一个网页都不能正常访问,貌似这HttpClient不能太多线程,怎么破
首先, 你得告诉我们, 报的是什么异常. 第二, 系统支持多线程, 但你开那么多, 其实没有太多好处了, 用于建立线程的开销, 线程间切换的开销也是很大的. 一般, 不建议创建超过CPU核心线程数*2个.(你的U是4核8线程的, 那么, 不建议建立超过8个进程线程.) 第三, 是不是使用了代理, 第四, 要控制对同一个域的访问周期, 比如两个请求之间没有间隔, 有的域, 会做限制, 直接封掉你的IP或者什么. 这个也要小心处理. 使用代理也一样, 一个代理的频率太高, 这个代理也会被封.
MikeCheers 2014-03-22
  • 打赏
  • 举报
回复
代理的不稳定性是很难预判的,至少我还没有找到很好的办法,往往尝试连接代理服务器会花费很长的时间. 如果是想快速响应,并跳过无效代理,可以使用线程,通过ManualResetEvent的Wait方法阻塞等待,判断超时.如果超时,可以切换别的代理.当然,这个等待超时时间可以包括连接+等待回复的时间. 我的处理方式是建立一个大的代理服务器地址列表, 给每个代理服务器地址分配一个权重. 每次取随机数*权重,排序,用值最大的代理服务器地址. 权重的初始值是一样的, 再通过成功连接数,失败连接数,平均连接花费时间等,动态调整权重.
threadroc 2014-03-21
  • 打赏
  • 举报
回复
引用 7 楼 JulioHuang 的回复:
[quote=引用 2 楼 threadroc 的回复:] [quote=引用 1 楼 JulioHuang 的回复:] 试试.net 4.5的HttpClient呢?
亲,貌似4.5没有HttpClient这个类,只有WebClient,而且WebClient没有设置超时的方法的[/quote]namespace System.Net.Http // Summary: // Provides a base class for sending HTTP requests and receiving HTTP responses // from a resource identified by a URI. public class HttpClient[/quote] 感谢这位大大,原来需要引用程序集,,的确是可以的,可是只能4.5不能4.0有点吭...XP不能用 { 难道两全其美就这么难么...
threadroc 2014-03-21
  • 打赏
  • 举报
回复
引用 8 楼 wmg494005678 的回复:
连接超时还是读写超时?
应该是连接超时的,不用代理没问题,用了无效代理,就直接卡20~30秒,应该是验证代理卡了20~30秒
threadroc 2014-03-21
  • 打赏
  • 举报
回复
引用 7 楼 JulioHuang 的回复:
[quote=引用 2 楼 threadroc 的回复:] [quote=引用 1 楼 JulioHuang 的回复:] 试试.net 4.5的HttpClient呢?
亲,貌似4.5没有HttpClient这个类,只有WebClient,而且WebClient没有设置超时的方法的[/quote]namespace System.Net.Http { // Summary: // Provides a base class for sending HTTP requests and receiving HTTP responses // from a resource identified by a URI. public class HttpClient[/quote] 还有这位大大,我有时候用HttpClient 的GetAsync方法,会发送keep-alive,有时候不会,这什么情况呀,我想每次都有keep-alive
threadroc 2014-03-20
  • 打赏
  • 举报
回复
引用 5 楼 threadroc 的回复:
另外用代理,如果代理不可用会本地访问,这怎么破...
5楼的问题无视把,是代码写错了,还是关注楼主的问题吧
threadroc 2014-03-20
  • 打赏
  • 举报
回复
另外用代理,如果代理不可用会本地访问,这怎么破...
wmg494005678 2014-03-20
  • 打赏
  • 举报
回复
连接超时还是读写超时?
黄亮 2014-03-20
  • 打赏
  • 举报
回复
引用 2 楼 threadroc 的回复:
[quote=引用 1 楼 JulioHuang 的回复:] 试试.net 4.5的HttpClient呢?
亲,貌似4.5没有HttpClient这个类,只有WebClient,而且WebClient没有设置超时的方法的[/quote]namespace System.Net.Http { // Summary: // Provides a base class for sending HTTP requests and receiving HTTP responses // from a resource identified by a URI. public class HttpClient
threadroc 2014-03-19
  • 打赏
  • 举报
回复
引用 3 楼 tigerspring 的回复:
request.Proxy = null; //Skip auto proxy detect
我知道不用代理是正常的,但是我要在用代理的情况下用啊
tigerspring 2014-03-19
  • 打赏
  • 举报
回复
request.Proxy = null; //Skip auto proxy detect
threadroc 2014-03-19
  • 打赏
  • 举报
回复
引用 1 楼 JulioHuang 的回复:
试试.net 4.5的HttpClient呢?
亲,貌似4.5没有HttpClient这个类,只有WebClient,而且WebClient没有设置超时的方法的
黄亮 2014-03-19
  • 打赏
  • 举报
回复
试试.net 4.5的HttpClient呢?

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧