在用C#实现一个Http消息推送时,用了WebClient.UpdateString,结果发现该函数在http消息没有返回时会被阻塞。
经测试,阻塞超时是100秒。如果使用默认超时,将会大大影响推送效率,经检索资料,发现WebClient类没有超时设置。
这里查到有两种方案解决。
方案1
重写WebClient类,增加超时设置,实现起来还是比较简单
public class WebClientEx : WebClient
{
public int Timeout {get; set;}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
request.Timeout = Timeout;
return request;
}
}
使用
var myClient = new WebClientEx();
myClient.Timeout = 900000 // Daft timeout period
myClient.UploadData(myUri, myData);
方案2
使用异步方法 WebClient.UploadStringAsync (Uri, String)
此方法的缺点是,一旦调用失败,无法直接获取调用的url,但也很容易解决,有两个办法
1)使用WebClient.UploadStringAsync (Uri, String, String, Object)这个方法,第三个参数可以存放自定义数据
然后在回调函数中从 e.UserState中获取;
2)同方案1中重写WebClient类,并添加成员变量m_url,调用时自己保存相关信息,等进入回调函数时可以使用。
相关代码:
private static void UploadStringCallback2(Object sender, UploadStringCompletedEventArgs e)
{
//string reply = (string)e.Result; 发生异常时Result是null,正常时是返回信息
WebClientEx wc = (WebClientEx)sender;
string str = wc.GetRequestURL();
string strlog = e.UserState.ToString();
strlog = e.Error.ToString();
}
}
public class WebClientEx : WebClient
{
public string m_strURL;
public int Timeout { get; set; }
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
request.Timeout = Timeout;
m_strURL = address.OriginalString;
return request;
}
public string GetRequestURL()
{
return m_strURL;
}
}
//===使用
WebClientEx wc = new WebClientEx();
//WebClient wc = new WebClientEx();
//wc.Timeout = 3000;
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");//可以post提交
wc.Encoding = Encoding.UTF8;
//string[] pinfo = ConfigurationManager.AppSettings["EnableProxy"].Split('|');
//if (pinfo[0].ToLower() == "true")
//{
// wc.Proxy = new WebProxy(pinfo[1], int.Parse(pinfo[2]));
//}
string postData = "a=12345&b=abcde";
string m_url = "http://localhost:16910/testpost.ashx";
wc.m_strURL = m_url;
string result = "";
Stopwatch timer = new Stopwatch();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(UploadStringCallback2);
timer.Start();
try
{
wc.UploadStringAsync(new Uri(m_url), "POST", postData, (object)m_url);
//wc.UploadString(m_url, postData);
}
catch (System.Exception ex)
{
result = ex.Message;
}
timer.Stop();
result +=" use:" +(timer.ElapsedMilliseconds / 1000).ToString();
另,在使用异步下载时,有朋友说网络中断会导致卡死,并给了解决方案,贴在这里备用
创建计时器监视响应情况,过期则取消下载



































































































































































































参考:
https://stackoverflow.com/questions/1237966/how-can-i-change-the-time-limit-for-webclient-uploaddata
http://www.cnblogs.com/heros/archive/2009/07/06/1517997.html