我将首先了解异步性和非 UI 冻结应用程序的重要性。我真正喜欢的整个 async/await 世界,甚至是 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
遇到的问题我
不能使用第 3 方库,因为这是一个库并且不想要第 3 方依赖项。
这应该是同步的确实是有原因的,不会详细说明,这不是设计问题,而是设计功能。
使用 WebRequest Begin/End 操作,请求/响应通过回调发生。这很棒,而且效果很好。现在没有 API 可以同步调用 Web 服务,Windows Phone 8 SDK 不支持 GetRequest/GetRespone。
我尝试使用互斥锁并调用一个Wait
在 Web 服务类调用内部的方法,Mutex.WaitOne()
假设它将暂停调用方法,直到完成请求并获得响应的最后一个回调将发出释放信号。
理论上它应该可以工作,但是在调用 时WaitOne()
,最后一个回调永远不会返回来完成这项工作。
然后我想使用IAsyncResult
BeginXyz/EndXyz 方法的返回值IsComplete
在 while 循环中检查,如果为真则中断继续。没有成功。
那么,我想知道,是否有一种可行的高效解决方案来同步调用 Web 服务?
搜索谷歌和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;
}
}
谢谢你。