Nit*_*aul 23 c# async-await c#-5.0 windows-phone-8
我如何使用Async/Await模式转换我传统的HttpWebRequest"POST"调用,这里有我附加我当前的代码,任何人请帮我转换这个代码使用Async/Await模式为Windows Phone 8.
public void GetEnvironmentVariables(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
CredentialsCallback = getResultCallback;
ErrorCallback = getErrorCallback;
var uri = new Uri(BaseUri);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
var jsonObject = new JObject
{
new JProperty("apiKey",_api),
new JProperty("affiliateId",_affid),
};
var serializedResult = JsonConvert.SerializeObject(jsonObject);
byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);
request.BeginGetRequestStream(GetRequestStreamCallback, new object[] { request, requestBody });
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
var request = (HttpWebRequest)((object[])asynchronousResult.AsyncState)[0];
using (var postStream = request.EndGetRequestStream(asynchronousResult))
{
var byteArray = (byte[])((object[])asynchronousResult.AsyncState)[1];
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
}
request.BeginGetResponse(GetResponseCallback, request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
var request = (HttpWebRequest)asynchronousResult.AsyncState;
try
{
var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
CredentialsCallback(Credentails);
else
{
if (Credentails != null)
ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
}
}
}
catch (WebException we)
{
var reader = new StreamReader(we.Response.GetResponseStream());
string responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
ErrorCallback(we);
}
}
Run Code Online (Sandbox Code Playgroud)
Ian*_*ths 20
由于Windows Phone 8似乎不提供您需要的TAP方法,GetRequestStreamAsync因此首先要做的是编写一个小包装器来为自己提供:
public static class WebRequestAsyncExtensions
{
public static Task<Stream> GetRequestStreamAsync(this WebRequest request)
{
return Task.Factory.FromAsync<Stream>(
request.BeginGetRequestStream, request.EndGetRequestStream, null);
}
public static Task<WebResponse> GetResponseAsync(this WebRequest request)
{
return Task.Factory.FromAsync<WebResponse>(
request.BeginGetResponse, request.EndGetResponse, null);
}
}
Run Code Online (Sandbox Code Playgroud)
注意使用Task.Factory.FromAsync- 这是获得await基于APM的异步API 的友好包装器的首选方法,例如提供的那些WebRequest.这比使用Task.Factory.StartNew其他人建议的效率要高得多,因为这会启动新线程,而这不需要.
有了这个,您现在可以像在可以使用这些TAP样式方法的平台上那样编写代码(例如,Windows 8商店应用程序,桌面应用程序等):
public async Task GetEnvironmentVariablesAsync(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
CredentialsCallback = getResultCallback;
ErrorCallback = getErrorCallback;
var uri = new Uri(BaseUri);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
var jsonObject = new JObject
{
new JProperty("apiKey",_api),
new JProperty("affiliateId",_affid),
};
var serializedResult = JsonConvert.SerializeObject(jsonObject);
byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);
// ASYNC: using awaitable wrapper to get request stream
using (var postStream = await request.GetRequestStreamAsync())
{
// Write to the request stream.
// ASYNC: writing to the POST stream can be slow
await postStream.WriteAsync(requestBody, 0, requestBody.Length);
}
try
{
// ASYNC: using awaitable wrapper to get response
var response = (HttpWebResponse) await request.GetResponseAsync();
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// ASYNC: using StreamReader's async method to read to end, in case
// the stream i slarge.
string responseString = await reader.ReadToEndAsync();
Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
CredentialsCallback(Credentails);
else
{
if (Credentails != null)
ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
}
}
}
catch (WebException we)
{
var reader = new StreamReader(we.Response.GetResponseStream());
string responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
ErrorCallback(we);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意带有// ASYNC:注释的四行- 这些显示了我进行更改的位置.我已经崩溃了你的方法到一个,因为一旦你使用的是一个)可能async与await和b)不是试图从一个方法传递的东西到下一个使用状态参数容易得多.
请注意,这些中的第二个和第四个实际上使您以前同步执行的操作异步化:将数据写入请求流,并从响应流中读取数据.对于一个小请求,这可能无关紧要,但如果正在传输大量数据,则同步调用Write或ReadToEnd可能阻塞.幸运的是,尽管Windows Phone 8似乎缺少TAP方法WebRequest,但它确实提供了它们Stream,StreamReader因此无需编写任何扩展方法即可实现.