如何使Web服务POST同步

时间:2013-08-29 23:26:01

标签: c# web-services windows-phone-8 synchronous

我将首先了解异步性和非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;
                    }
            }

谢谢。

0 个答案:

没有答案