【问题标题】:How do I actually get the response of an async web request from outside the method?我实际上如何从方法外部获得异步 Web 请求的响应?
【发布时间】:2012-03-26 17:51:58
【问题描述】:

我有点困惑。我正在尝试以异步方式发布到我的 Web 服务,理想情况下我想启动请求,在 UI 上显示加载微调器,然后当异步请求完成时处理响应,如果有一个错误,则显示错误,或对结果执行其他操作。

这是我的代码,我在这里调用请求并传入一些数据。

private void SignInExecute()
{

        if (Username == null || Password == null)
        {
            LoginOutput = "Please provide a username or password.";
        }
        else
        {
            this.webService.SendLoginRequest("http://localhost:3000/client_sessions", "username=" + Username + "&password=" + Password);

        }

}

这是实际的网络请求代码:

public void SendLoginRequest(string url, string postdata)
{
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

        request.Method = "POST";

        request.ContentType = "application/x-www-form-urlencoded";

        request.Accept = "application/json";

        byte[] byteArray = Encoding.UTF8.GetBytes(postdata);

        request.CookieContainer = new CookieContainer();

        request.ContentLength = byteArray.Length;

        Stream dataStream = request.GetRequestStream();

        dataStream.Write(byteArray, 0, byteArray.Length);

        dataStream.Close();

        ((HttpWebRequest)request).KeepAlive = false;

        request.BeginGetResponse(new AsyncCallback(GetLoginResponseCallback), request);


    }

    private static void GetLoginResponseCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

        // End the operation
        HttpWebResponse response =  (HttpWebResponse)request.EndGetResponse(asynchronousResult);
        Stream streamResponse = response.GetResponseStream();
        StreamReader streamRead = new StreamReader(streamResponse);
        string responseString = streamRead.ReadToEnd();

        Console.WriteLine(responseString);

        // Close the stream object
        streamResponse.Close();
        streamRead.Close();
        response.Close();
    }

总结一下。我希望能够将响应返回给最初调用 Web 请求开始的对象。有什么帮助吗?

【问题讨论】:

  • Winforms/webforms/silverlight/什么?
  • WPF,不觉得太重要了。更新了标签以反映它。

标签: c# wpf asynchronous


【解决方案1】:

您需要告诉BeginGetResponse 返回到通过SynchronizationContext.Current 调用它的同一上下文。像这样(代码没有适当的错误检查,所以你应该好好考虑一下)(另外,Platinum Azure 是正确的,你应该使用using 让你的流正确关闭(并保证):

在您的 SendLoginRequest 中:

//Box your object state with the current thread context
object[] boxedItems = new []{request, SynchronizationContext.Current};
request.BeginGetResponse(new AsyncCallback(GetLoginResponseCallback), 
    boxedItems);

getresponse代码:

private static void GetLoginResponseCallback(IAsyncResult asynchronousResult)
{
//MY UPDATE 
    //Unbox your object state with the current thread context
    object[] boxedItems = asynchronousResult.AsyncState as object[];
    HttpWebRequest request = boxedItems[0] as HttpWebRequest;
    SynchronizationContext context = boxedItems[1] as SynchronizationContext;

    // End the operation
    using(HttpWebResponse response =  
        (HttpWebResponse)request.EndGetResponse(asynchronousResult))
    {
        using(Stream streamResponse = response.GetResponseStream())
        {
            using(StreamReader streamRead = new StreamReader(streamResponse))
            {
                string responseString = streamRead.ReadToEnd();

                Console.WriteLine(responseString);
//MY UPDATE
                //Make an asynchronous call back onto the main UI thread 
                //(context.Send for a synchronous call)
                //Pass responseString as your method parameter 
                //If you have more than one object, you will have to box again
                context.Post(UIMethodToCall, responseString);
            }
        }
    }
}

实现您的 UI 处理

public static void UIMethodCall(object ObjectState)
{
    String response = ObjectState as String;
    label1.Text = String.Format("Output: {0}", response);
    //Or whatever you need to do in the UI...
}

不过,现在我会先测试一下。我对 Microsoft 实现事件驱动异步的理解是响应是上下文感知的,并且知道要返回哪个上下文。因此,在假设您不在同一个上下文中之前,请尝试更新 UI 进行测试(如果您不在调用 (UI) 线程上,这将导致线程上下文异常)

【讨论】:

  • 您可能应该使用 try/finally 或 using 以确保在发生异常时正确关闭资源。
  • @PlatinumAzure 我已经更新了代码,因为这是更好的做法,你是对的。您还提醒我注意代码没有错误检查。
  • 除了最后一行 context.Post(UIMethodToCall, StateObjectThatUIWillActOn); 我想我理解你写的内容你能进一步扩展一下吗?
  • @benjgorman 更新了我的代码。现在让我知道这是否有意义?
  • 确实如此,但是 UIMethodCall 是否与 Web 请求属于同一类。还是与 SignInExecute 方法在同一个类中?此行还有一个 NullException。 HttpWebRequest 请求 = boxedItems[0] 作为 HttpWebRequest;我不确定如何解决?
猜你喜欢
  • 2020-12-27
  • 1970-01-01
  • 2017-04-13
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多