1. 程式人生 > >.Net WebRequest異步請求與WebClient異步請求

.Net WebRequest異步請求與WebClient異步請求

str down cal lse 容器 RM pic 展示 BE

很多情況下一般會使用同步方式發出請求,直到響應後再做後續的邏輯處理等,但有時候後續的邏輯處理不依賴於請求的結果或者是可以掛起等到響應後再處理,又或者是為了解決UI“假死”的現象,這時可以使用異步請求

使用WebRequest實例中的BeginGetResponse方法異步獲取響應結果,其中參數callback是委托類型,state是自定義的對象,state用於保存一些信息,在callback對應的方法中可能需要用到這些信息。

下面用一個例子說明,假設需要請求url,該url對應是一張圖片,異步獲取後展示到PictureBox中(該例子基於winform的一個窗體中)

winform中定義了存放數據的變量

List<byte> lstBuffer = new List<byte>();
byte[] buffers = new byte[8];

在具體需要請求服務器的地方創建WebRequest實例,並調用BeginGetResponse方法

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如下:

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。

如果是使用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);
    }
}

.Net WebRequest異步請求與WebClient異步請求