C# 如何从方法外部获取异步web请求的响应?
我有点困惑。我试图以异步方式发布到我的web服务,理想情况下,我希望启动请求,在UI上显示加载微调器,然后在异步请求完成时处理响应,如果有错误,则显示错误,或者对结果执行另一个操作 这是我的代码,我在这里调用请求并传入一些数据C# 如何从方法外部获取异步web请求的响应?,c#,wpf,asynchronous,C#,Wpf,Asynchronous,我有点困惑。我试图以异步方式发布到我的web服务,理想情况下,我希望启动请求,在UI上显示加载微调器,然后在异步请求完成时处理响应,如果有错误,则显示错误,或者对结果执行另一个操作 这是我的代码,我在这里调用请求并传入一些数据 private void SignInExecute() { if (Username == null || Password == null) { LoginOutput = "Please provide a
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请求代码:
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请求启动调用的对象。有什么帮助吗?您需要告诉
开始响应
返回到通过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);
}
}
}
}
实现用户界面处理
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)线程上,这将导致线程上下文异常)Winforms/webforms/silverlight/what?WPF不认为添加它太重要。更新标记以反映它。您可能应该使用try/finally或using
,以确保在出现异常时正确关闭资源。@PlatinumAzure我已经更新了代码,因为这是更好的做法,您是对的。您还提醒了我注意代码没有错误检查。除了最后一行context.Post(UIMethodToCall,StateObjectThatUIWillActOn)之外,我想我理解您编写的内容;你能进一步扩展一下吗?@benjgorman更新了我的代码。现在让我知道这是否有意义?是的,UIMethodCall是否与web请求在同一个类中。或者它是否与SignenExecute方法在同一个类中?此行还有一个NullException。HttpWebRequest request=boxedItems[0]作为HttpWebRequest;我不确定如何修复它?