2012-05-06 13 views
1

私はWebサービスに接続するための簡単なアプリケーションを作っていますが、非同期要求の管理に問題があります。メインスレッドをブロックせずに非同期のHttpWebResponseを返す方法は?

問題は基本的に非同期HttpWebRequestを作成し、HttpWebResponseを返すProcessRequest関数にあります。リクエストが非同期であるため、戻り値に問題があり、ProcessRequestメソッドを呼び出してHttpWebResponseオブジェクトを待機する関数で問題が発生しています。

ところで、リクエスト自体は完全に機能しており、すでに関数内でテストされているので、HttpWebResponseを返す必要はありません。

私が言ったように、これは私がC#、.NET、およびWindows Phone開発に初めて触れる初めての話です。

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  

そして、これはコードです::Visual Studioが投げされていること(そのことについてはまたWebRequests)

エラーは事前に

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 

ありがとう!

+0

代理人が実行される前にProcessRequestメソッドが完了するでしょうか?私はC#5で新しい非同期/待機機能を使用する必要があると思うが、個人的に自分で使ったことはありませんし、WP7 7.1で利用できるかどうかもわかりません... http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern –

+1

これは非同期コードを簡略化するのに役立つかもしれませんが、まだCTPなので、Itを実装するつもりはありません。とにかくありがとう。 はい、WP7プラットフォームで利用できます。 – asendra

答えて

1

通常と同じように非同期プログラミングを行うことはできません。ここでは.Netは別のスレッドで非同期の部分を実行している、どのように通信することができますか?ですから、あなたは、あなたのProcessRequestメソッドを使ってデリゲートを渡すことができます。これはHttpWebResponseのパラメータをとります。応答

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は、新しい署名を持っていますハンドル

Action<HttpWebResponse> actionDelegate = DoAfterGettingResponse; 
ProcessRequest(indexPath, "GET", actionDelegate, queryParams); 

機能:

は、このようなあなたのメソッドを呼び出します。

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のを渡すイベントを発生し、リスナーで応答を処理することができます。

+0

これは間違いなく機能し、基本的には私が考えていたものです。 ProcessRequestメソッドにコールバックを渡し、要求が完了したときにそのコールバックを実行します。ありがとう! とにかく、誰かがより良いアプローチを知っている場合は、共有してください! – asendra

関連する問題