我将首先了解异步性和非UI冻结应用程序的重要性。整个异步/等待我真正喜欢的世界,甚至是APM,或使用Task
做重工作。
这一切都很好,但我有一个场景,我真的需要等待Web服务POST完成然后继续。
public void DoSomeWorkNow()
{
// Do stuff...
// Do more stuff...
// Make the web service call..
// The request should finish and I should continue doing stuff....
// Do stuff...
}
我不能使用async / await,即使我想要,也不能解决问题。
我可以使用Task.FromAsync
,但您可以参考我在here遇到的问题
我不能使用第三方库,因为这是一个库,不需要第三方依赖。
这应该是同步的原因,不会涉及细节,这不是设计问题,而是设计特征。
使用WebRequest开始/结束操作,请求/响应发生在回调中。 这很好,工作正常。现在没有API可以同步调用Web服务,Windows Phone 8 SDK不支持GetRequest / GetRespone。
我曾尝试使用Mutex并调用Wait
方法,该方法在Web服务类调用Mutex.WaitOne()
内部,假设它将暂停调用方法,直到完成请求的最后一个回调并获取响应将发出免费信号。
理论上它应该可以工作,但是当调用WaitOne()
时,最后一次回调永远不会返回来完成这项工作。
然后我想从BeginXyz / EndXyz方法中使用IAsyncResult
返回值检查while循环中的IsComplete
,如果为true则中断以继续。没有成功。
所以,我想知道,是否有一种可行的有效解决方案来同步调用Web服务?
搜索Google和stackoverflow,没有找到可行的解决方案。
更新
以下是我尝试的一些代码:
public void ExecuteRequest(string url, string requestData, string filePath)
{
WebRequest request = WebRequest.Create(new Uri(url));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
((HttpWebRequest)request).UserAgent = "Tester";
request.Headers["UserName"] = "Tester";
DataWebRequest webRequestState = new DataWebRequest
{
Data = requestData,
FileName = filePath,
Request = request
};
IAsyncResult requestResult = request.BeginGetRequestStream(ar =>
{
DataWebRequest webRequestData = (DataWebRequest )ar.AsyncState;
HttpWebRequest requestStream = (HttpWebRequest)webRequestData.Request;
string data = webRequestData.Data;
// Convert the string into a byte array.
byte[] postBytes = Encoding.UTF8.GetBytes(data);
try
{
// End the operation
// Here the EndGetRequestStream(ar) throws exception System.InvalidOperationException:
// Operation is not valid due to the current state of the object
using (Stream endGetRequestStream = requestStream.EndGetRequestStream(ar))
{
// Write to the request stream.
endGetRequestStream.Write(postBytes, 0, postBytes.Length);
}
requestStream.BeginGetResponse(GetResponseCallback, webRequestData);
}
catch (WebException webEx)
{
WebExceptionStatus status = webEx.Status;
WebResponse responseEx = webEx.Response;
Debug.WriteLine(webEx.ToString());
}
}, webRequestState);
// The below while loop is actually breaking as the IsCompleted is true, but an
// exception System.InvalidOperationException is thrown after a while
while (true)
{
if (requestResult.IsCompleted) break;
}
IAsyncResult responseResult = request.BeginGetResponse(ar =>
{
DataWebRequest webRequestData = (DataWebRequest)ar.AsyncState;
HttpWebRequest httpWebRequest = (HttpWebRequest)webRequestData.Request;
try
{
// End the operation
using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(ar))
{
HttpStatusCode rcode = response.StatusCode;
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
// The Response
string responseString = streamRead.ReadToEnd();
if (!string.IsNullOrWhiteSpace(webRequestData.FileName))
{
FileRepository fileRepo = new FileRepository();
fileRepo.Delete(webRequestData.FileName);
}
Debug.WriteLine("Response : {0}", responseString);
// Maybe do some other stuff....
}
}
catch (WebException webEx)
{
WebExceptionStatus status = webEx.Status;
WebResponse responseEx = webEx.Response;
Debug.WriteLine(webEx.ToString());
}
}, webRequestState);
// This while loop never actually ends!!!
while (true)
{
if (responseResult.IsCompleted) break;
}
}
谢谢。