亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

.NET中的async和await關鍵字使用及Task異步調用實例

2020-01-24 02:39:54
字體:
來源:轉載
供稿:網友

其實早在.NET 4.5的時候M$就在.NET中引入了async和await關鍵字(VB為Async和Await)來簡化異步調用的編程模式。我也早就體驗過了,現在寫一篇日志來記錄一下順便湊日志數量(以后面試之前可以用這個“復習”一下)。

(一)傳統的異步調用

在比較“古老”的C#程序中經??梢钥吹絀AsyncResult、BeginInvoke之類的異步調用“蹤跡”。先來簡單的復習一下吧。

假如我們有一個方法生成字符串,而生成這個字符串需要10秒中的時間:

復制代碼 代碼如下:

public class WasteTimeObject
{
    public string GetSlowString(int begin, int length)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = begin; i < begin + length; i++)
        {
            sb.Append(WasteTime(i) + " ");
        }

        return sb.ToString();
    }

    private string WasteTime(int current)
    {
        System.Threading.Thread.Sleep(1000);
        return current.ToString();
    }
}

我們再做一個窗口,用來請求這個方法并把字符串顯示到文本框中。使用同步調用肯定會把UI線程阻塞掉,要想不把UI阻塞掉就要另起一個線程了?;镜牟襟E如下:

創建一個異步調用的委托:

復制代碼 代碼如下:

public delegate string GetSlowStringDelegate(int begin, int length);

然后呢,再異步調用這個委托:

復制代碼 代碼如下:

private void button1_Click(object sender, EventArgs e)
{
    WasteTimeObject ad = new WasteTimeObject();
    GetSlowStringDelegate d = ad.GetSlowString;

    textBox1.Text = "Requesting string, please wait...";

    IAsyncResult ar = d.BeginInvoke(1, 10, TaskComplete, d);
}

這里的BeginInvoke會在原來的基礎上再附加兩個參數:表示執行完畢后的回調方法AsyncCallBack,最后一個參數可以是任何對象,以便從回調方法中訪問它。不過一般情況都是傳遞的委托實例,以便獲取調用的結果。

當然我們也可以不用回調方法,這樣就只好不斷地循環查詢是否執行完成了。

然后我們就要編寫AsyncCallBack這個回調方法了,它接受一個IAsyncResult類型的對象表示異步調用的結果:

復制代碼 代碼如下:

private void TaskComplete(IAsyncResult ar)
{
    if (ar == null) return;
    GetSlowStringDelegate d = ar.AsyncState as GetSlowStringDelegate;
    if (d == null) throw new Exception("Invalue object type");
    string result = d.EndInvoke(ar);
    this.Invoke(new Action(() => UpdateTextResult(result)));
}

調用委托實例的EndInvoke方法并傳入IAsyncResult類型的對象用以獲取GetSlowString的返回結果。

回調方法是委托線程調用的,因此它不能直接訪問UI,所以我們使用窗體的Invoke方法在主線程中顯示結果。如果委托方法拋出異常,將會在EndInvoke時拋出。

(二)使用Task類型

可以看到使用傳統的辦法編寫異步調用很麻煩,特別是如果這種調用很多,那么我們的程序就會變成很復雜,邏輯很亂。

.NET 4.5提供的新的異步變成模式就很好地解決了這個問題(其實本質上應該是.NET自動實現了很多操作),使編寫異步代碼和同步調用一樣邏輯清晰。

首先來看看微軟的例子:

復制代碼 代碼如下:

private async Task SumPageSizesAsync()
{
    // To use the HttpClient type in desktop apps, you must include a using directive and add a
    // reference for the System.Net.Http namespace.
    HttpClient client = new HttpClient();

    // Equivalently, now that you see how it works, you can write the same thing in a single line.
    byte[] urlContents = await client.GetByteArrayAsync(url);
    // . . .
}

可以看出,使用await關鍵字后,.NET會自動把返回結果包裝在一個Task類型的對象中。對于這個示例,方法是沒有返回結果的。而對有返回結果的方法,就要使用Task<T>了:

復制代碼 代碼如下:

public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

總而言之,使用await表達式時,控制會返回到調用此方法的線程中;在await等待的方法執行完畢后,控制會自動返回到下面的語句中。發生異常時,異常會在await表達式中拋出。

對于我們這個例子,我們編寫的代碼如下:

復制代碼 代碼如下:

private async void button1_Click(object sender, EventArgs e)
{
    textBox1.Text = "Requesting string, please wait...";

    WasteTimeObject ad = new WasteTimeObject();

    string result = await Task.Run(() => ad.GetSlowString(1, 10));

    //Update UI to display the result
    textBox1.Text = result;
}

我們使用Task類新建一個工作線程并執行。當然我們也可以像M$給的例子那樣改造一下GetSlowString,這樣就不需要加上Task.Run了。(基本上,這種方法都會以Async后綴結尾。)

如何?原來的:創建異步委托→回調一氣呵成。另外還有一點,await下面的語句是由主線程調用的,不是由新的線程調用,所以我們可以直接訪問UI。

(三)取消執行和顯示進度

最后一個要記錄的,就是如何給異步調用添加進度條,并能讓用戶取消操作。界面就是下面這樣:

使用最終完成的代碼來說明吧。首先改造GetSlowString方法,使之支持取消和匯報進度:

復制代碼 代碼如下:

public string GetSlowString(int begin, int length, IProgress<int> progress, CancellationToken cancel)
{
    StringBuilder sb = new StringBuilder();

    for (int i = begin; i < begin + length; i++)
    {
        sb.Append(WasteTime(i) + " ");

        cancel.ThrowIfCancellationRequested();

        if (progress != null)
            progress.Report((int)((double)(i - begin + 1) * 100 / length));
    }

    return sb.ToString();
}

IProgress<T>類型的對象有一個Report方法,執行這個方法實際上會調用自定義的更新進度的方法,這個方法(使用委托或匿名方法皆可)是在生成Progress<T>對象的時候指定的:

復制代碼 代碼如下:

IProgress<int> progress = new Progress<int>((progressValue) => { progressBar1.Value = progressValue; });

神奇的是,這個方法是由主線程調用的,如果不是這樣,它就不能更新我們界面上的控件。所以說微軟提供的新機制幫我們簡化了很多工作。

CancellationToken用于指定該方法“綁定”的取消上下文,如果這個對象執行過Cancel方法(用戶點擊了Cancel按鈕),那么訪問ThrowIfCancellationRequested時就會拋出OperationCanceledException類型的異常。這種機制的靈活性在于中止執行的位置是可以自行確定的,不會出現取消時自己都不知道執行到哪行代碼的情況。

總而言之,單擊request按鈕的代碼我們修改如下:

復制代碼 代碼如下:

private async void button1_Click(object sender, EventArgs e)
{

    cancelSource = new CancellationTokenSource();
    IProgress<int> progress = new Progress<int>((progressValue) => { progressBar1.Value = progressValue; });

    textBox1.Text = "Requesting string, please wait...";
    button1.Enabled = false; button2.Enabled = true;

    WasteTimeObject ad = new WasteTimeObject();

    try
    {
        string result = await Task.Run(() => ad.GetSlowString(1, 10, progress, cancelSource.Token),
            cancelSource.Token);
        //Update UI to display the result
        textBox1.Text = result;
        button2.Enabled = false;  //Disable cancel button
    }
    catch (OperationCanceledException)
    {
        textBox1.Text = "You canceled the operation.";
    }

}

取消按鈕的代碼就很簡單了:

復制代碼 代碼如下:

private void button2_Click(object sender, EventArgs e)
{
    if (cancelSource != null) cancelSource.Cancel();
    button2.Enabled = false;
}

至此,Task機制的初步體驗就到此完成。以后有機會在研究下更高階的內容吧。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产欧美日韩高清| 亚洲二区在线播放视频| 亚洲一区二区三区毛片| 66m—66摸成人免费视频| 国产精品女主播视频| 日韩电影在线观看中文字幕| 91精品国产一区| 色综合影院在线| 欧美性xxxxxx| 国产aⅴ夜夜欢一区二区三区| 国产精品一区二区三区免费视频| 国产一区二区三区在线观看视频| 欧美日韩国产区| 亚洲女人天堂色在线7777| 亚洲成人精品视频| 中文字幕亚洲欧美在线| 国产成人免费av电影| 97成人超碰免| 午夜精品一区二区三区在线视| 97在线精品视频| 亚洲一区二区三区四区视频| 欧美久久精品午夜青青大伊人| 久久精品国产欧美亚洲人人爽| 欧美性黄网官网| 91热精品视频| 亚洲精品理论电影| 国产精品aaa| 欧美激情高清视频| 亚洲国产精品电影在线观看| 亚洲毛片一区二区| 亚洲奶大毛多的老太婆| 中文字幕自拍vr一区二区三区| 欧美色欧美亚洲高清在线视频| 亚洲字幕一区二区| 亚洲人成电影网站| 日韩欧美有码在线| 亚洲欧美精品伊人久久| 91中文在线视频| 国产精品视频一区二区高潮| 国产精品久久久久久久久久新婚| 亚洲新中文字幕| 欧美精品电影在线| 国产精品久久久av久久久| 欧美日韩一区二区免费在线观看| 久久成人精品电影| 国产美女久久精品| 丁香五六月婷婷久久激情| 欧洲成人在线视频| 91精品成人久久| 精品精品国产国产自在线| 国产精品久久久av久久久| 精品国产福利视频| 国产有码在线一区二区视频| 在线精品视频视频中文字幕| 国产精品免费福利| 国产成人一区三区| 国产亚洲视频中文字幕视频| 国产69精品久久久| 中文字幕亚洲一区二区三区| 国产精品美女免费| 91超碰caoporn97人人| 国产乱肥老妇国产一区二| zzjj国产精品一区二区| 国产欧美一区二区三区久久人妖| 久久综合免费视频影院| 国产精品久久婷婷六月丁香| 午夜精品一区二区三区视频免费看| 欧美激情亚洲激情| 久久青草精品视频免费观看| 亚洲在线www| 亚洲成人精品久久久| 91精品国产九九九久久久亚洲| 亚洲人成免费电影| 中文字幕欧美日韩va免费视频| 日韩精品视频在线播放| 亚洲精品国产精品国产自| 亚洲精品视频久久| 亚洲精选一区二区| 国产精品永久免费| 91国产一区在线| 亚洲精品日产aⅴ| 精品国产欧美成人夜夜嗨| 精品久久久久久久久久| 国产精品一区二区女厕厕| 日韩av一区二区在线观看| 最新国产精品亚洲| 成人精品视频99在线观看免费| 91精品久久久久久久久| 精品日韩美女的视频高清| 欧美日韩精品在线播放| 丝袜亚洲另类欧美重口| 美日韩丰满少妇在线观看| 亚洲a在线播放| 欧美激情亚洲精品| 91国产精品视频在线| 国产精品入口夜色视频大尺度| 久久九九有精品国产23| 伊人久久大香线蕉av一区二区| 国产精品久久久久久久电影| 91免费人成网站在线观看18| 欧美性猛交xxxxx水多| 国产丝袜一区二区| 国产日韩中文在线| 中文字幕日韩欧美精品在线观看| 亚洲第一区第二区| 日本中文字幕久久看| 欧美专区中文字幕| 国产在线精品成人一区二区三区| 亚洲图片欧洲图片av| 亚洲最大的免费| 91在线国产电影| 日本精品久久久久久久| 51久久精品夜色国产麻豆| 国内精品视频久久| 国产午夜精品全部视频播放| 69av在线播放| 中文字幕精品www乱入免费视频| 久久久精品国产网站| 亚洲国产日韩欧美在线99| 亚洲精品永久免费精品| 97精品国产97久久久久久免费| 成人性生交大片免费看视频直播| 亚洲护士老师的毛茸茸最新章节| 亚洲成avwww人| 欧美韩日一区二区| 日本免费久久高清视频| 综合国产在线观看| 51ⅴ精品国产91久久久久久| 久久97精品久久久久久久不卡| 国产亚洲视频中文字幕视频| 亚洲欧美中文日韩在线| 欧美乱妇40p| 国产精品网址在线| 亚洲综合日韩中文字幕v在线| 欧美高清激情视频| 欧美激情视频三区| 亚洲国产精品系列| 久久久精品在线观看| 亚洲国产欧美一区二区三区同亚洲| 日韩在线欧美在线| 欧美疯狂性受xxxxx另类| 在线a欧美视频| 国产日本欧美一区二区三区在线| 亚洲bt欧美bt日本bt| 最近2019年手机中文字幕| 国产精品久久久久久久午夜| 亚洲午夜未删减在线观看| 国产自产女人91一区在线观看| 最近2019中文免费高清视频观看www99| 欧美亚洲激情在线| 91精品国产乱码久久久久久蜜臀| 亚洲一级黄色av| 午夜精品久久久久久久久久久久久| 欧美国产一区二区三区| 亚洲色图13p| 色老头一区二区三区| 精品久久久久久国产| 国产精品成人免费电影| 精品国产欧美一区二区三区成人| 日韩在线一区二区三区免费视频| 久久精品影视伊人网| 亚洲欧美在线一区| 亚洲第一福利网站| 亚洲欧美日韩直播|