Je crée une application simple pour me connecter à un webservice, et j'ai des problèmes pour gérer les requêtes asynchrones.Comment retourner une HttpWebResponse asynchrone sans bloquer le thread principal?
Le problème est avec la fonction ProcessRequest, qui effectue fondamentalement un HttpWebRequest asynchrone, et renvoie le HttpWebResponse. Comme la requête est asynchrone, j'ai des problèmes avec la valeur de retour, et avec les fonctions appelant la méthode ProcessRequest et attendant l'objet HttpWebResponse. Par ailleurs, la requête en elle-même fonctionne parfaitement, déjà testé dans les fonctions, donc je n'ai pas besoin de retourner une réponse HttpWebResponse.
J'espère que je suis clair, comme je l'ai dit, c'est la première fois que je touche au développement de C#, .NET et Windows Phone. (Et WebRequests pour cette question)
Les erreurs que Visual Studio est de lancer sont:
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
Et ceci est le code:
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
Merci à l'avance!
Votre méthode ProcessRequest se terminerait avant même que votre délégué s'exécute, n'est-ce pas? Je pense que vous devrez utiliser les nouvelles fonctions async/await dans C# 5, mais je ne les ai jamais utilisées personnellement et je ne suis pas sûr qu'elles soient disponibles dans WP7 7.1 ... http://www.codeproject.com/Articles/127291/C-5-0-vNext-Nouveau-Asynchronous-Pattern –
Cela pourrait aider à simplifier le code asynchrone, mais parce que c'est toujours CTP je ne vais pas l'implémenter. Merci quand même. Et oui, il est disponible pour la plateforme WP7. – asendra