【发布时间】:2015-04-28 13:03:37
【问题描述】:
我刚开始使用 C#,所以请原谅我对如何使用它的无知(如果有的话)。 我有一个执行以下代码的登录按钮
private void Login_Click(object sender, RoutedEventArgs e)
{
if (email_box.Text != "" && password_box.Password != "") {
string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" + @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
Regex reg = new Regex(strRegex);
if (reg.IsMatch(email_box.Text))
{
ApiCall request = new ApiCall();
request.requestData = "{\"sessions\": {\"links\":{\"user\":{\"email\":\"" + email_box.Text + "\",\"password\":\"" + password_box.Password + "\" }}}}";
request.requestMethod = Constants.httpMethods[0];
request.resource_url = "/sessions";
var response = request.initialize_request();
//Once i get the response string, i will deserialize it here and use it to do other things, like navigate to a new page an any other neccessary things to do!
}
else
{
recover.Text = "Please provide a valid email address.";
}
}
else
{
recover.Text = "Email and Password cannot be Empty";
}
}
该方法初始化这个类并调用initialize_request(),后者又调用GetRequestStreamCallback,后者也调用GetResponseStreamCallback。 p>
初始化请求应该发回一个字符串,该字符串在 GetResponseStreamCallBack 中设置,但它似乎在最后两个方法执行之前发回了一个字符串。 Soo,我读到了 async 和 await 并且我尝试使用它们,但是 Visual Studio 说 Cannot await "method group" 我在哪里等待
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using System.Net;
using Newtonsoft.Json;
using PrintMyPic.ApiJsonObjects;
using PrintMyPic;
using System.Windows.Navigation;
namespace MyApp
{
class ApiCall
{
public static string api_url = "http://myappsapiurl/api";
public static string content_type = "application/vnd.api+json";
public string requestData;
public string requestMethod;
public string resource_url; // the rest of the api url
public string requestResponse;
public async Task<string> initialize_request()
{
Debug.WriteLine("the resource used is "+ resource_url);
System.Uri myUri = new System.Uri(api_url+resource_url);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(myUri);
request.ContentType = content_type;
request.Method = requestMethod;
request.Accept = content_type;
request.BeginGetRequestStream(new AsyncCallback(await GetRequestStreamCallback), request);
Debug.WriteLine("have we returned yet?");
return requestResponse;
}
private async Task GetRequestStreamCallback(IAsyncResult callbackResult)
{
Debug.WriteLine("we are in the second method");
HttpWebRequest webrequest = (HttpWebRequest)callbackResult.AsyncState;
Stream postStream = webrequest.EndGetRequestStream(callbackResult);
byte[] byteArray = Encoding.UTF8.GetBytes(requestData);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
webrequest.BeginGetResponse(new AsyncCallback( await GetResponsetStreamCallback), webrequest);
}
private void GetResponsetStreamCallback(IAsyncResult callbackResult)
{
Debug.WriteLine("we are in the third method");
try
{
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
string responseString = "";
Stream streamResponse = response.GetResponseStream();
StreamReader reader = new StreamReader(streamResponse);
responseString = reader.ReadToEnd();
streamResponse.Close();
reader.Close();
response.Close();
requestResponse = responseString;
}
catch (Exception e)
{
//show user-friendly error message as well as detailed one.
//for better UI, consider using WPToolKit's CustomMessageBox to show these
Debug.WriteLine("something wrong happened. \nDetails: " + e.HResult.ToString());
}
}
}
}
非常感谢任何解决此问题的帮助,我希望 initialize_request() 执行,等待 GetRequestStreamCallback 和 GetResponseStreamCallback 完成,然后返回请求响应
[更新] 根据 cmets 部分,我被建议使用 AutoResetEvent
namespace MyApp
{
class ApiCall
{
public static string api_url = "http://myappapirul/api";
public static string content_type = "application/vnd.api+json";
public string requestData;
public string requestMethod;
public string resource_url; // the rest of the api url
public string requestResponse;
public static AutoResetEvent objAuto = new AutoResetEvent(false);
public string initialize_request()
{
Debug.WriteLine("the resource used is "+ resource_url);
System.Uri myUri = new System.Uri(api_url+resource_url);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(myUri);
request.ContentType = content_type;
request.Method = requestMethod;
request.Accept = content_type;
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
objAuto.WaitOne();
Debug.WriteLine("have we returned yet?");
return requestResponse;
}
private void GetRequestStreamCallback(IAsyncResult callbackResult)
{
Debug.WriteLine("we are in the second method");
HttpWebRequest webrequest = (HttpWebRequest)callbackResult.AsyncState;
Stream postStream = webrequest.EndGetRequestStream(callbackResult);
byte[] byteArray = Encoding.UTF8.GetBytes(requestData);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
webrequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), webrequest);
}
private void GetResponsetStreamCallback(IAsyncResult callbackResult)
{
Debug.WriteLine("we are in the third method");
try
{
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
string responseString = "";
Stream streamResponse = response.GetResponseStream();
StreamReader reader = new StreamReader(streamResponse);
responseString = reader.ReadToEnd();
streamResponse.Close();
reader.Close();
response.Close();
requestResponse = responseString;
}
catch (Exception e)
{
//show user-friendly error message as well as detailed one.
//for better UI, consider using WPToolKit's CustomMessageBox to show these
Debug.WriteLine("something wrong happened. \nDetails: " + e.HResult.ToString());
}
Debug.WriteLine("we are about to return to initialize_request");
objAuto.Set();
}
}
}
现在的问题是,GetResponsetStreamCallback 永远不会启动,而且看起来我永远不会返回,因为Debug.WriteLine("have we returned yet?"); 永远不会被执行!
【问题讨论】:
-
您不需要异步的 GetRequestStreamCallback 方法。将其签名更改为 private void GetRequestStreamCallback(IAsyncResult callbackResult)
-
@VictorMukherjee 我试过了,但仍然是'Debug.WriteLine(“我们回来了吗?”);'在这两种方法中的任何一种之前执行!
-
另外,如果你想使用异步模型,你会想使用 request.GetRequestStreamAsync。
-
Debug.WriteLine("我们回来了吗?");大多数情况下会在这两个方法之前执行,因为 request.BeginGetRequestStream 方法是异步执行的,但是由于它没有使用任何 async 关键字,所以不能等待任务。但是,您可以使用 AutoResetEvent 在 BeginGetRequestStream 之后等待 initialize_request 方法,并从 GetResponsetStreamCallback 设置 AutoResetEvent。
-
@VictorMukherjee 我已经尝试过 AutoRestEvent,请参阅更新后的问题!谢谢
标签: c# windows-phone-8 httpwebrequest async-await