FCL小應用系列———–如何利用APM實現HttpWebRequest非同步發送接收

來源:互聯網
上載者:User

APM(非同步編程模型)在.net編程中隨處可見,HttpWebRequest類也實現了APM,可供使用者使用。今天做了一個小實驗,總結一下。還是先看代碼吧。

using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Text;<br />using System.Web;<br />using System.Net;<br />using System.IO;<br />using System.Windows.Forms;</p><p>namespace ConsoleApplication1<br />{<br /> class Program<br /> {<br /> static void Main(string[] args)<br /> {<br /> Console.WriteLine(<br /> System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());<br /> XqHttpClient xc = new XqHttpClient();<br /> XqFormData xf = new XqFormData();<br /> xf.Add("username", "使用者名稱字");<br /> xf.Add("password", "使用者密碼");<br /> xf.Add("loginsubmit", "登 陸");<br /> int j=0;<br /> for (j = 0; j < 200; j++)<br /> {<br /> xc.SendPostRequest("http://blog.runsky.com/batch.login.php?action=login", xf.formData);<br /> xc.SendGetRequest("http://www.baidu.com");<br /> }<br /> Console.WriteLine("main thread.........................");<br /> System.Threading.Thread.Sleep(1000);<br /> }<br /> }<br /> //構建表單資料,並UrlEncoded<br /> class XqFormData<br /> {<br /> public XqFormData(Encoding e)<br /> {<br /> this.formEncoding = e;<br /> }<br /> public XqFormData()<br /> {<br /> this.formEncoding = Encoding.GetEncoding("gb2312");<br /> }<br /> public string formData<br /> {<br /> get<br /> {<br /> return str.Substring(0, str.Length - 1);<br /> }<br /> set<br /> {<br /> }<br /> }<br /> private Encoding formEncoding;<br /> private string str;<br /> public void Add(string name, string value)<br /> {<br /> str += HttpUtility.UrlEncode(name, this.formEncoding);<br /> str += "=";<br /> str += HttpUtility.UrlEncode(value, Encoding.GetEncoding("gb2312"));<br /> str += "&";<br /> }<br /> }<br /> /// <summary><br /> /// HTTP通用用戶端<br /> /// </summary><br /> class XqHttpClient<br /> {<br /> //伺服器端的編碼方式UTF8/GB2312<br /> private Encoding encodingServer = Encoding.GetEncoding("gb2312");<br /> private string strURI; //請求行,URLEncoded的UNICODE表示<br /> private string strFormData; //表單資料,URLEncoed的UNICODE表示<br /> CookieContainer currentCookieContainer = new CookieContainer(); //當前的Cookie容器<br /> private string strResponseBody = ""; //伺服器返回的訊息主體</p><p> //重載<br /> public void SendPostRequest(string uri, string formData)<br /> {<br /> this.strURI = uri;<br /> this.strFormData = formData;<br /> SendPostRequest();<br /> }<br /> //重載<br /> public void SendGetRequest(string uri)<br /> {<br /> this.strURI = uri;<br /> SendGetRequest();<br /> }<br /> //BeginGetResponse完成之後,此處有CLR其他線程執行<br /> public void GetResponseDone(object state) //state自動被賦值為iResult<br /> {<br /> Console.WriteLine("GetResponseDone: " +<br /> System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());<br /> try<br /> {<br /> IAsyncResult ir = (IAsyncResult)state;<br /> HttpWebRequest req = (HttpWebRequest)ir.AsyncState;<br /> HttpWebResponse resp = (HttpWebResponse)(req.EndGetResponse(ir));</p><p> //讀取訊息標題</p><p> //讀取訊息主體<br /> Stream ResponseStream = resp.GetResponseStream();<br /> StreamReader sr = new StreamReader(ResponseStream, this.encodingServer);</p><p> while (sr.Peek() >= 0)<br /> {<br /> char[] recv = new char[1024];<br /> sr.Read(recv, 0, recv.Length);<br /> strResponseBody += new string(recv);<br /> }<br /> }<br /> catch (Exception e)<br /> {<br /> Console.WriteLine(e.ToString());<br /> }<br /> //Console.WriteLine(this.strResponseBody);<br /> }<br /> //發送GET請求<br /> public void SendGetRequest()<br /> {<br /> try<br /> {<br /> HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strURI);<br /> req.Method = "GET";<br /> req.CookieContainer = this.currentCookieContainer;</p><p> //發送並取得伺服器回應<br /> //APM版本<br /> req.BeginGetResponse(<br /> new AsyncCallback(this.GetResponseDone),<br /> req);<br /> //此時,系統會自動把<br /> //ir作為GetResponseDone的參數傳送,並把req賦值給ir的AsynState成員。<br /> }<br /> catch (Exception e)<br /> {<br /> Console.WriteLine(e.ToString());<br /> }</p><p> }<br /> //非同步呼叫<br /> public void GetRequestStreamDone(object state)<br /> {<br /> Console.WriteLine("GetRequestStreamDone: " +<br /> System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());<br /> IAsyncResult ir = (IAsyncResult)state;<br /> HttpWebRequest req = (HttpWebRequest)ir.AsyncState;<br /> Stream requestStream = req.EndGetRequestStream(ir);</p><p> StreamWriter sw = new StreamWriter(requestStream, Encoding.ASCII);<br /> sw.Write(this.strFormData); //寫入表單資料(urlencoded)<br /> sw.Close();<br /> requestStream.Close();<br /> //發送並取得伺服器回應<br /> req.BeginGetResponse(new AsyncCallback(this.GetResponseDone), req);<br /> }<br /> //發送POST請求<br /> public void SendPostRequest()<br /> {<br /> try<br /> {<br /> HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strURI);<br /> //構建標題<br /> req.ContentType = "application/x-www-form-urlencoded";<br /> req.ContentLength = this.strFormData.Length;<br /> req.Method = "POST";<br /> req.CookieContainer = this.currentCookieContainer;</p><p> //構建表單資料<br /> req.BeginGetRequestStream(this.GetRequestStreamDone, req);</p><p> }<br /> catch (Exception e)<br /> {<br /> Console.WriteLine(e.ToString());<br /> }<br /> }<br /> }<br />}<br />

其實APM使用起來相當簡單直觀。大概步驟如下:

(1)調用HttpWebRequest.BeginXXX(AsyncCallback callback, object state)

此函數發起非同步呼叫,並把這個代表這個非同步作業的IAsyncResult對象引用自動作為callback回呼函數的實參傳遞,state則賦值給IAsyncResult對象的AsyncState成員。

(2)在回呼函數裡調用HttpWebRequest.EndXXX(ir),完成響應讀取。

 

在APM模型裡,其實回呼函數是在等待的操作完成之後由CLR自動開啟新線程執行的。

另外需要注意的是,對於同一個HttpWebRequest對象,不能同時進行混合使用同步和非同步方法呼叫,BeginGetRequestStream()和BeginGetResponse()必須同時使用,不能把GetRequestStream()和BeginGetResponse()混合使用。也就是說一個特定的HttpWebRequest對象,要麼執行非同步作業,要麼執行同步操作,不能混合約步和非同步函數。實際上以首先調用的函數為準,如果先調用同步函數,即使以後調用非同步函數,還是會按照同步方式執行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.