C# 異步操作 async await


在編程的過程中,我們會遇到很多需要異步操作的場景。比如要下載一個文件,如果使用同步的方式進行下載,那么UI操作就會被卡住,這時最好能夠使用異步的方式進行下載。在C#中,很早就開始支持異步的操作了,只不過早期的方法寫起來有些麻煩。到了C# 5.0的時候,直接添加了兩個關鍵字:async 和 await,這下對異步操作的支持可謂是達到了完美。下面我們就通用一個簡單的 demo 看一下它們的基本用法。

下載一個文件

我們先看看用同步的方式下載一個文件:

private void btnOldDownload_Click(object sender, EventArgs e)
{
    using(WebClient wc = new WebClient())
    {
        // 我們嘗試去下載 python 的安裝包。
        wc.DownloadFile("https://www.python.org/ftp/python/3.5.2/python-3.5.2-amd64.exe", "python.exe");
    }
    lbMessage.Text = "下載完成。";
}

在執行 DownloadFile 方法的過程中,UI線程被卡死,整個的下載過程中應用程序都處於沒響應的狀態。這當然是不能接受的,所以我們應該使用下面的異步方式進行文件的下載。

異步下載文件

我們先看一下使用早期的異步代碼去下載文件:

private void OldAsyncDownload_Click(object sender, EventArgs e)
{
    using (WebClient wc = new WebClient())
    {
        // 我們嘗試去下載 python 的安裝包。
        // 下載完成時會有事件通知。
        wc.DownloadFileCompleted += Wc_DownloadFileCompleted;
        wc.DownloadFileAsync(new Uri("https://www.python.org/ftp/python/3.5.2/python-3.5.2-amd64.exe"), "python.exe");
    }
}
private void Wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    lbMessage.Text = "下載完成。";
}

好吧,事情變得稍微有點復雜了。一個簡單的下載邏輯居然被分隔到了兩個方法中!在第一個方法中掛載 DownloadFileCompleted 事件,然后啟動下載。下載完成后通過 DownloadFileCompleted 事件處理函數進行通知。如果您能夠習慣於這樣的寫法,其實C# 早期提供的異步編程接口已經足夠用了,因為這也正是異步操作真正的實現方式。

但是,作為程序員,我們是不會滿足的,永遠不會…

async await 方式

在C# 5.0 中引入了 async 和 await 關鍵字,它們使得異步操作的實現更加簡單、容易!

private async void btnMyAsync_Click(object sender, EventArgs e)
{
    using (WebClient wc = new WebClient())
    {
        // 我們嘗試去下載 python 的安裝包。
        Task task = wc.DownloadFileTaskAsync("https://www.python.org/ftp/python/3.5.2/python-3.5.2-amd64.exe", "python.exe");
        // 可以在這里執行代碼。
        await task;
    }
    lbMessage.Text = "下載完成。";
}

注意代碼中 async 和 await 關鍵字的位置,這樣代碼就是以異步方式去執行下載邏輯,整個過程中UI 操作不會被阻塞掉。是不是很神奇呢?

這段代碼最大的魔力在於它和同步下載文件的代碼幾乎相同!每個 人都喜歡寫順序執行的代碼,這樣的代碼邏輯也最清晰。async 和 await 的最大優勢就是把人腦感覺簡單的代碼轉換為真正的異步操作邏輯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM