我如何真正得到来自外部方法异步Web请求的响应? [英] How do I actually get the response of an async web request from outside the method?

查看:109
本文介绍了我如何真正得到来自外部方法异步Web请求的响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点困惑。我试图张贴到我的网络服务以异步的方式,理想的我要开始的要求,显示在用户界面上加载微调,然后当异步请求完成处理响应,要么显示一个错误,如果有一个,或者做的结果其他操作。

I'm a little confused. I'm trying to post to my web service in an async manner, ideally I want to start the request, show a loading spinner on the UI and then when the async request finishes process the response and either show an error if there is one, or do another operation with the result.

下面是我的code,我这里所说的请求,并通过一些数据。

Here is my code, I call the request here and pass some data in.

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);

        }

}

这是实际的Web请求code:

And here is the actual web request code:

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请求启动的对象。任何帮助吗?

So to sum up. I want to be able to return the response back to the object which originally gave the call for the web request to start. Any help?

推荐答案

您需要告诉 BeginGetResponse 回到相同的上下文中,它是通过<称为code> SynchronizationContext.Current 。像这样的东西(的code没有适当的错误检查,所以你应该考虑一下正确)(另外,白金Azure是正确的,你应该使用使用让你流正常关闭(和保证):

You need to tell the BeginGetResponse to go back to the same context in which it was called via SynchronizationContext.Current. Something like this (the code does not have proper error checking, so you should think about that properly) (Also, Platinum Azure is correct that you should use a using to let your streams close properly (and guaranteed):

在您SendLoginRequest:

In your SendLoginRequest:

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

在GetResponse的code:

The getresponse code:

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)线程)

Now, I would test this out first, though. My understanding of Microsoft's implementation of event driven async was that the response was context-aware, and knew which context to return to. So, before jumping to the assumption that you are not on the same context, test it out by trying to update the UI (this will cause a thread context exception if you are not on the calling (UI) thread)

这篇关于我如何真正得到来自外部方法异步Web请求的响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆