异步使用HttpWebRequest而不阻塞UI线程
问题描述:
我试图在WinForms应用程序中异步使用HttpWebRequest
和HttpWebResonse
而不会阻塞我的UI线程。异步使用HttpWebRequest而不阻塞UI线程
我看到这个similar SO Question,它解释了如何做到这一点。但是,我不能100%确定接受的答案是正确的做法。接受的答案是使用BeginGetResponse
。
的BeginGetResponse方法需要一些同步设置任务给 完成(DNS解析,代理检测,并且TCP套接字连接, 例如)之前该方法变得异步的。因此,不应在用户界面(UI)线程 上调用此方法,因为它可能需要一些时间(通常为几秒)。
有人可以请我提供正确的方法来做到这一点。这里是我的,我试图做工作“正常”,而不挡住了我的UI线程C#功能:
private IDictionary<string, object> CreateWebRequest(string endPoint, string method, string data, bool addAuthHeader)
{
var req = (HttpWebRequest)WebRequest.Create(endPoint);
req.Method = method;
if (addAuthHeader)
{
req.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + _accessToken.AccessToken);
}
if (!string.IsNullOrEmpty(data))
{
var utfenc = new UTF8Encoding();
byte[] buffer = utfenc.GetBytes(data);
req.ContentLength = buffer.Length;
req.ContentType = "application/x-www-form-urlencoded";
using (Stream strm = req.GetRequestStream())
{
strm.Write(buffer, 0, buffer.Length);
strm.Close();
}
}
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
if (_accessToken == null)
{
throw;
}
var responseError = (HttpWebResponse)e.Response;
if (responseError.StatusCode == HttpStatusCode.Unauthorized)
{
var stackTrace = new StackTrace();
var q = stackTrace.GetFrame(1).GetMethod().Name;
RefreshAccessCode();
req = (HttpWebRequest)WebRequest.Create(endPoint);
req.Method = method;
if (addAuthHeader)
{
req.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + _accessToken.AccessToken);
}
response = (HttpWebResponse)req.GetResponse();
}
}
string jsonResponse = null;
if (response != null)
using (Stream stream = response.GetResponseStream())
{
if (stream != null)
{
using (var reader = new StreamReader(stream))
{
jsonResponse = reader.ReadToEnd();
}
}
}
return DeserializeResponse(jsonResponse);
}
答
如果你打开另外WebRequest的东西,我的System.Net.WebClient风扇。它使用System.Threading.Tasks而不是BeginGetResponse()和EndGetResonse()。
public async Task<Dictionary<string, object>> CreateWebRequest(string endPoint, string method, string data, bool addAuthHeader)
{
WebClient client = new WebClient();
if (addAuthHeader)
{
client.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + _accessToken.AccessToken);
}
byte[] buffer = null;
if (!string.IsNullOrEmpty(data))
{
var utfenc = new UTF8Encoding();
buffer = utfenc.GetBytes(data);
}
else
{
buffer = new byte[0];
}
return await client.UploadDataTaskAsync(endPoint, method, buffer)
.ContinueWith((bytes) =>
{
string jsonResponse = null;
using (var reader = new StreamReader(new MemoryStream(bytes)))
{
jsonResponse = reader.ReadToEnd();
}
return DeserializeResponse(jsonResponse);
});
}
}
答
要使用现有的代码,再加上一点意在UI线程上执行的方法,以及在单独的线程上创建您的Web请求。当Web请求完成后,您可以调用UI线程上的最终方法。所以,一个简单的版本是:
//do some stuff that wont block the ui thread here
ThreadPool.QueueUserWorkItem((o) =>
{
IDictionary<string, object> result =
CreateWebRequest("lalala", "lol", "butts", true);
BeginInvoke(OnAsyncWebRequestComplete, result);
}, null);
private void OnAsyncWebRequestComplete(IDictionary<string, object> result)
{
//do some stuff on the UI thread here
}
是不是@ Isak对另一个问题的回答你链接了你要找的东西? – vlad 2013-02-26 21:14:05