你可能寫了個假異步,並不能提升請求線程池的吞吐量

不知道用什麼詞形容,就叫它假異步吧。html

寫異步方法,async 和 await 要一路寫到底,不然就是假異步,並不能提升請求線程池的吞吐量。數據庫

真正的異步,個人理解是這樣的:好比調用一個查詢接口,在當前線程,把SQL扔給數據庫,當前線程釋放,去幹別的事情,數據庫查詢完了,通知我,我再在另外一個線程裏(也多是剛纔釋放的那個線程,也可能不是)拿查詢結果,返回給客戶端,數據庫查詢比較耗時,數據庫查詢的時候,對線程是0佔用。
 
HttpUtil.HttpGet方法:
/// <summary>
/// HttpGet
/// </summary>
/// <param name="url">url路徑名稱</param>
/// <param name="cookie">cookie</param>
public static string HttpGet(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
{
    try
    {
        // 設置參數
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        request.CookieContainer = cookie;
        request.Method = "GET";
        request.ContentType = "text/plain;charset=utf-8";

        if (headers != null)
        {
            foreach (string key in headers.Keys)
            {
                request.Headers.Add(key, headers[key]);
            }
        }

        //發送請求並獲取相應迴應數據
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
        //直到request.GetResponse()程序纔開始向目標網頁發送Post請求
        Stream instream = response.GetResponseStream();
        StreamReader sr = new StreamReader(instream, Encoding.UTF8);
        //返回結果網頁(html)代碼
        string content = sr.ReadToEnd();
        instream.Close();
        return content;
    }
    catch (Exception ex)
    {
        LogUtil.Error(ex);
        return string.Empty;
    }
}
View Code

HttpUtil.HttpGetAsync方法:api

/// <summary>
/// HttpGetAsync
/// </summary>
/// <param name="url">url路徑名稱</param>
/// <param name="cookie">cookie</param>
public static async Task<string> HttpGetAsync(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
{
    try
    {
        // 設置參數
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        request.CookieContainer = cookie;
        request.Method = "GET";
        request.ContentType = "text/plain;charset=utf-8";

        if (headers != null)
        {
            foreach (string key in headers.Keys)
            {
                request.Headers.Add(key, headers[key]);
            }
        }

        //發送請求並獲取相應迴應數據
        HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
        //直到request.GetResponse()程序纔開始向目標網頁發送Post請求
        Stream instream = response.GetResponseStream();
        StreamReader sr = new StreamReader(instream, Encoding.UTF8);
        //返回結果網頁(html)代碼
        string content = sr.ReadToEnd();
        instream.Close();
        return content;
    }
    catch (Exception ex)
    {
        LogUtil.Error(ex);
        return string.Empty;
    }
}
View Code

測試代碼:cookie

/// <summary>
/// 測試1
/// </summary>
private async void button1_Click(object sender, EventArgs e)
{
    //task是本身寫的獨立線程池,爲了防止測試過程對CLR線程池和異步線程池形成干擾
    _task.Run(() =>
    {
        Thread.Sleep(200);

        int workerThreads1, completionPortThreads1, workerThreads2, completionPortThreads2;
        ThreadPool.GetMaxThreads(out workerThreads1, out completionPortThreads1);
        ThreadPool.GetAvailableThreads(out workerThreads2, out completionPortThreads2);
        Log("假異步 已使用輔助線程:" + (workerThreads1 - workerThreads2) + ", 已使用異步線程:" + (completionPortThreads1 - completionPortThreads2));
    });

    string str = await GetDataAsync();
}

/// <summary>
/// 測試2 
/// </summary>
private async void button2_Click(object sender, EventArgs e)
{
    //task是本身寫的獨立線程池,爲了防止測試過程對CLR線程池和異步線程池形成干擾
    _task.Run(() =>
    {
        Thread.Sleep(200);

        int workerThreads1, completionPortThreads1, workerThreads2, completionPortThreads2;
        ThreadPool.GetMaxThreads(out workerThreads1, out completionPortThreads1);
        ThreadPool.GetAvailableThreads(out workerThreads2, out completionPortThreads2);
        Log("真異步 已使用輔助線程:" + (workerThreads1 - workerThreads2) + ", 已使用異步線程:" + (completionPortThreads1 - completionPortThreads2));
    });

    string str = await GetDataAsync2();
}

/// <summary>
/// 假異步
/// </summary>
private async Task<string> GetDataAsync()
{
    return await Task.Run<string>(() =>
    {
        //接口耗時大約1秒
        return HttpUtil.HttpGet("http://localhost:8500/api/test/TestGet?val=1", null, null);
    });
}

/// <summary>
/// 真異步
/// </summary>
/// <returns></returns>
private async Task<string> GetDataAsync2()
{
    //接口耗時大約1秒
    return await HttpUtil.HttpGetAsync("http://localhost:8500/api/test/TestGet?val=1", null, null);
}
View Code

測試截圖:異步

我想知道 WebRequest 類的 GetResponseAsync 方法是怎麼實現的,反正使用.NET提供的類,我是沒法實現這樣的方法。async

這篇隨筆若是有錯誤,請指正,我只是拋磚引玉,提出疑問或者說假設。ide

async await 要一路寫到底啊,重構壓力真大。測試

相關文章
相關標籤/搜索