不少狀況下通常會使用同步方式發出請求,直到響應後再作後續的邏輯處理等,但有時候後續的邏輯處理不依賴於請求的結果或者是能夠掛起等到響應後再處理,又或者是爲了解決UI「假死」的現象,這時能夠使用異步請求服務器
使用WebRequest實例中的BeginGetResponse方法異步獲取響應結果,其中參數callback是委託類型,state是自定義的對象,state用於保存一些信息,在callback對應的方法中可能須要用到這些信息。異步
下面用一個例子說明,假設須要請求url,該url對應是一張圖片,異步獲取後展現到PictureBox中(該例子基於winform的一個窗體中)url
winform中定義了存放數據的變量spa
List<byte> lstBuffer = new List<byte>(); byte[] buffers = new byte[8];
在具體須要請求服務器的地方建立WebRequest實例,並調用BeginGetResponse方法code
string url = "http://localhost/1.jpg"; var request = WebRequest.Create(url); request.BeginGetResponse(RespCallBack, request);
RespCallBack方法以下,此處ar.AsyncState也就是上面調用BeginGetResponse方法中參數state對應的信息,也就是request
private void RespCallBack(IAsyncResult ar) { var request = ar.AsyncState as WebRequest; var response = request?.EndGetResponse(ar); Stream responseStream = response?.GetResponseStream(); responseStream?.BeginRead(buffers, 0, 8, ReadCallBack, responseStream); }
因爲是異步,此處讀數據也是異步讀取,ReadCallBack以下:orm
private void ReadCallBack(IAsyncResult ar) { using (var responseStream = ar.AsyncState as Stream) { if (responseStream == null) return; var read = responseStream.EndRead(ar); if (read > 0) { lstBuffer.AddRange(buffers); responseStream.BeginRead(buffers, 0, 8, ReadCallBack, responseStream); } else { lstBuffer.AddRange(buffers); Stream s = new MemoryStream(lstBuffer.ToArray()); pictureBox1.Image = Image.FromStream(s); pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; responseStream.Dispose(); } } }
每次讀必定的字節,填充到指定的容器中(lstBuffer),當數據尚未讀取完畢就一直調用responseStream.BeginRead(buffers, 0, 8, ReadCallBack, responseStream);對象
當讀取完畢後,將讀取的數據(lstBuffer)轉換成圖片,賦值給pictureBox。blog
若是是使用WebClient的方式代碼量就少不少,調用DownloadDataAsync方法發起異步請求,註冊事件DownloadDataCompleted,當異步請求完成的時候會觸發 Wc_DownloadDataCompleted事件,Wc_DownloadDataCompleted事件中DownloadDataCompletedEventArgs類型的參數e包含一些信息,其中e.Result就是請求響應的結果(byte[]類型)事件
var wc = new WebClient(); wc.DownloadDataAsync(new Uri("http://localhost/1.jpg")); wc.DownloadDataCompleted += Wc_DownloadDataCompleted;
private void Wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) { using (MemoryStream ms = new MemoryStream(e.Result)) { if (pictureBox1 != null) pictureBox1.Image = Image.FromStream(ms); } }