簡體   English   中英

如何在不阻塞主線程的情況下返回異步HttpWebResponse?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM