[英]How to call an async function synchronized without blocking the main thread?
[英]How to return an async HttpWebResponse without blocking the main thread?
我正在制作一个用于连接到Web服务的简单应用,但是在管理异步请求时遇到了问题。
问题出在函数ProcessRequest上,该函数基本上使异步HttpWebRequest并返回HttpWebResponse。 由于请求是异步的,因此返回值以及调用ProcessRequest方法并等待HttpWebResponse对象的函数遇到问题。
顺便说一句,该请求本身运行良好,已经在函数内部进行了测试,因此我无需返回HttpWebResponse。
我希望我能像我所说的那样使自己更清楚,这是我第一次接触c#、. NET和Windows Phone开发。 (以及与此相关的WebRequest)
Visual Studio引发的错误是:
1: Since 'System.AsyncCallback' returns void, a return keyword must not be followed by an object expression
2: Cannot convert lambda expression to delegate type 'System.AsyncCallback' because some of the return types in the block are not implicitly convertible to the delegate return type
这是代码:
namespace SimpleNoteConcept
{
public sealed class SimpleNote
{
private static readonly SimpleNote _instance = new SimpleNote();
private static string _authToken = string.Empty;
private static string _email = string.Empty;
private static string _authQsParams
{
get
{
if (string.IsNullOrEmpty(_authToken)) throw new SimpleNoteConceptAuthorisationException();
return string.Format("auth={0}&email={1}", _authToken, _email);
}
}
private SimpleNote() { }
public static SimpleNote Instance
{
get { return _instance; }
}
public bool Connect(string email, string password)
{
try
{
StringParamCheck("email", email);
StringParamCheck("password", password);
var data = string.Format("email={0}&password={1}", email, password);
var bytes = Encoding.GetEncoding("utf-8").GetBytes(data);
data = Convert.ToBase64String(bytes);
using (var resp = ProcessRequest( loginPath, "POST", content: data))
{
if (resp != null)
{
_authToken = resp.Cookies["auth"].Value;
_email = email;
System.Diagnostics.Debug.WriteLine("Connection established! -> " + _authToken);
return true;
}
return false;
}
}
catch (Exception)
{
throw;
}
}
public void GetIndex(int length = 100, string mark = null, DateTimeOffset? since = null)
{
try
{
string sinceString = null;
if (since.HasValue)
sinceString = Json.DateTimeEpochConverter.DateToSeconds(since.Value);
var queryParams = string.Format("{0}&length={1}&mark={2}&since={3}", _authQsParams, length, mark, sinceString);
using (var resp = ProcessRequest( indexPath, "GET", queryParams))
{
var respContent = ReadResponseContent(resp);
System.Diagnostics.Debug.WriteLine("GetIndex: " + respContent.ToString());
//var notes = JsonConvert.DeserializeObject<Objects.NoteEnumerable<T>>(respContent);
//return notes;
}
}
catch (WebException ex)
{
var resp = (HttpWebResponse)ex.Response;
switch (resp.StatusCode)
{
//401
case HttpStatusCode.Unauthorized:
throw new SimpleNoteConceptAuthorisationException(ex);
default:
throw;
}
}
catch (Exception) { throw; }
}
/// <summary>
/// Generic method to process a request to Simplenote.
/// All publicly expose methods which interact with the store are processed though this.
/// </summary>
/// <param name="requestPath">The path to the request to be processed</param>
/// <param name="method">The HTTP method for the request</param>
/// <param name="content">The content to send in the request</param>
/// <param name="queryParams">Queryparameters for the request</param>
/// <returns>An HttpWebResponse continaing details returned from Simplenote</returns>
private static HttpWebResponse ProcessRequest(string requestPath, string method,
string queryParams = null, string content = null)
{
try
{
var url = string.Format("{0}{1}{2}", "https://", domainPath, requestPath);
if (!string.IsNullOrEmpty(queryParams)) url += "?" + queryParams;
var request = WebRequest.Create(url) as HttpWebRequest;
request.CookieContainer = new CookieContainer();
request.Method = method;
request.BeginGetRequestStream((e) =>
{
using (Stream stream = request.EndGetRequestStream(e))
{
// Write data to the request stream
var bytesBody = Encoding.GetEncoding("utf-8").GetBytes(content);
stream.Write(bytesBody, 0, bytesBody.Length);
stream.Close();
stream.Dispose();
}
request.BeginGetResponse((callback) =>
{
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callback);
return response;
}
catch (WebException ex)
{
using (WebResponse Exresponse = ex.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)Exresponse;
System.Diagnostics.Debug.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream str = Exresponse.GetResponseStream())
{
string text = new StreamReader(str).ReadToEnd();
System.Diagnostics.Debug.WriteLine(text);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Message: " + ex.Message);
}
}, request);
}, request);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Reads the content from the response object
/// </summary>
/// <param name="resp">The response to be processed</param>
/// <returns>A string of the response content</returns>
private static string ReadResponseContent(HttpWebResponse resp)
{
if (resp == null) throw new ArgumentNullException("resp");
using (var sr = new StreamReader(resp.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
/// <summary>
/// String parameter helper method.
/// Checks for null or empty, throws ArgumentNullException if true
/// </summary>
/// <param name="paramName">The name of the paramter being checked</param>
/// <param name="value">The value to check</param>
private void StringParamCheck(string paramName, string value)
{
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(paramName, "Value must not be null or string.Empty");
}
} // Class End
} // Namespace End
提前致谢!
您不能像正常情况那样进行异步编程。 .Net在不同的线程中运行异步部分,如何进行通信? 因此,您可以做的是通过您的ProcessRequest方法传递一个委托。 它将采用HttpWebResponse的参数。
像这样调用您的方法:
Action<HttpWebResponse> actionDelegate = DoAfterGettingResponse;
ProcessRequest(indexPath, "GET", actionDelegate, queryParams);
处理响应的功能
public static void DoAfterGettingResponse(HttpWebResponse resp)
{
if (resp != null)
{
_authToken = resp.Cookies["auth"].Value;
_email = email;
System.Diagnostics.Debug.WriteLine("Connection established! -> " + _authToken);
}
//Do anything else with the response
}
ProcessRequest将具有新的签名。
private static HttpWebResponse ProcessRequest(
string requestPath, string method, Action<HttpWebResponse> reponseDelegate,
string queryParams = null, string content = null)
{
//Do what you are already doing
}
而您返回响应的地方,只需执行
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callback);
responseDelegate(response);
您可以这样做或使用事件,通过HttpWebResponse作为参数触发事件,并在侦听器中处理响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.