欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章弄懂C#中的async和await

 更新時(shí)間:2021年07月01日 11:22:36   作者:癡者工良  
這篇文章主要給大家介紹了如何通過一篇文章弄懂C#中async和await的相關(guān)資料,async和await相信大家應(yīng)該不陌生,讓異步處理變得更友好,本文通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

本文介紹async/Task。在學(xué)習(xí)該知識(shí)點(diǎn)過程中,一定要按照每一個(gè)示例,去寫代碼、執(zhí)行、輸出結(jié)果,自己嘗試分析思路。

async

微軟文檔:使用 async 修飾符可將方法、lambda 表達(dá)式或匿名方法指定為異步。

使用 async 修飾的方法,稱為異步方法。

例如:

為了命名規(guī)范,使用 async 修飾的方法,需要在方法名稱后面加上 Async 。

public async Task<int> TestAsync()  
{  
    // . . . .  
}
Lambda :


        static void Main()
        {
            Thread thread = new Thread(async () =>
            {
                await Task.Delay(0);
            });
        }
        public static async Task<int> TestAsync() => 666;

await

微軟文檔:await 運(yùn)算符暫停對(duì)其所屬的 async 方法的求值,直到其操作數(shù)表示的異步操作完成。

異步操作完成后,await 運(yùn)算符將返回操作的結(jié)果(如果有)。

好的,到此為止,async 和 await ,在官方文檔中的說明,就這么多。

從以往知識(shí)推導(dǎo)

這里我們不參考文檔和書籍的資料,不要看文檔和書籍中的示例,我們要一步步來從任務(wù)(Task)中的同步異步開始,慢慢摸索。去分析 async 和 await 兩個(gè)關(guān)鍵字給我們的異步編程帶來了什么樣的便利。

創(chuàng)建異步任務(wù)

場(chǎng)景:周六日放假了,可以打王者(一種游戲),但是昨天的衣服還沒有洗;于是用洗衣機(jī)洗衣服,清洗期間,開一局王者(一種游戲)。

我們可以編寫一個(gè)方法如下:

        static void Main()
        {
            Console.WriteLine("準(zhǔn)備洗衣服");

            // 創(chuàng)建一個(gè)洗衣服的任務(wù)
            Task<int> task = new Task<int>(() =>
            {
                // 模擬洗衣服的時(shí)間
                int time = new Random().Next(2, 6);
                Thread.Sleep(TimeSpan.FromSeconds(time));
                return time;
            });

            Console.WriteLine("開始洗衣服");

            // 讓洗衣機(jī)洗衣服
            task.Start();

            Console.WriteLine("我去打王者,讓洗衣機(jī)洗衣服");
            // 打王者
            Thread.Sleep(TimeSpan.FromSeconds(4));
            Console.WriteLine("打完王者了,衣服洗完了嘛?");

            Console.WriteLine(task.IsCompleted);
            if (task.IsCompleted)
                Console.WriteLine("洗衣服花的時(shí)間:" + task.Result);
            else
            {
                Console.WriteLine("在等洗衣機(jī)洗完衣服");
                task.Wait();
                Console.WriteLine("洗衣服花的時(shí)間:" + task.Result);
            }
            Console.WriteLine("洗完了,撈出衣服,曬衣服,繼續(xù)打王者去");
        }

創(chuàng)建異步任務(wù)并返回Task

上面的示例,雖然說,異步完成了一個(gè)任務(wù),但是這樣,將代碼都放到 Main ,可讀性十分差,還要其它什么規(guī)范之類的,不允許我們寫這樣的垃圾代碼。于是我們將洗衣服這個(gè)任務(wù),封裝到一個(gè)方法中,然后返回 Task 即可。

在 Program 類中,加入如下一個(gè)方法,這個(gè)方法用于執(zhí)行異步任務(wù),并且返回 Task 對(duì)象。

        /// <summary>
        /// 執(zhí)行一個(gè)任務(wù)
        /// </summary>
        /// <returns></returns>
        public static Task<int> TestAsync()
        {
            Task<int> task = new Task<int>(() =>
            {
                // 模擬洗衣服的時(shí)間
                int time = new Random().Next(2, 6);
                Thread.Sleep(TimeSpan.FromSeconds(time));
                return time;
            });
            task.Start();
            return task;
        }

Main 方法中,改成

        static void Main()
        {
            Console.WriteLine("準(zhǔn)備洗衣服");

            // 創(chuàng)建一個(gè)洗衣服的任務(wù)
            Task<int> task = TestAsync();
            ... ...

但是,兩者差別還是不大。

異步改同步

我們創(chuàng)建了異步方法,去執(zhí)行一個(gè)洗衣服的任務(wù);當(dāng)打完游戲后,需要檢查任務(wù)是否完成,然后才能進(jìn)行下一步操作,這時(shí)候就出現(xiàn)了 同步。為了保持同步和獲得執(zhí)行結(jié)果,我們使用了 .Wait() 、.Result 。

這里我們嘗試將上面的操作轉(zhuǎn)為同步,并且獲得執(zhí)行結(jié)果。

    class Program
    {
        static void Main()
        {
            int time = Test();
            // ... ...
        }

        /// <summary>
        /// 執(zhí)行一個(gè)任務(wù)
        /// </summary>
        /// <returns></returns>
        public static int Test()
        {
            Task<int> task = new Task<int>(() =>
            {
                // 模擬洗衣服的時(shí)間
                int time = new Random().Next(2, 6);
                Thread.Sleep(TimeSpan.FromSeconds(time));
                return time;
            });
            task.Start();
            return task.Result;
        }
    }

說說 await Task

Task 和 Task<TResult> ,前者是一個(gè)沒有返回結(jié)果的任務(wù),后者是有返回結(jié)果的任務(wù)。前面的文章中已經(jīng)使用過大量的示例,這里我們使用 await ,去完成一些完全相同的功能。

Task:

        public static void T1()
        {
            Task task = new Task(() => { });
            task.Wait();
        }
        public static async void T2()
        {
            Task task = new Task(() => {  });
            await task;
        }

說明,await 可以讓程序等待任務(wù)完成。

Task<TResult>:

       public void T3()
       {
           // 獲取 Task 任務(wù)對(duì)象,后面的邏輯過程可以弄成異步
           Task<int> task = TestAsync();

           // 任務(wù)是異步在執(zhí)行,我不理會(huì)他
           // 這里可以處理其它事情,處理完畢后,再獲取執(zhí)行結(jié)果
           // 這就是異步

           Console.WriteLine(task.Result);
       }

        public async void T4()
        {
            // 使用 await 關(guān)鍵字,代表等待執(zhí)行完成,同步
            int time = await TestAsync();
            Console.WriteLine(time);
        }

說明:await 可以讓程序等待任務(wù)執(zhí)行完成,并且獲得執(zhí)行結(jié)果。

看到?jīng)]有。。。await 關(guān)鍵字,作用是讓你等,是同步的,壓根不是直接讓你的任務(wù)變成異步后臺(tái)執(zhí)行的。

那為啥提到 async 、await,都是說跟異步有關(guān)?不急,后面解釋。

說說 async Task<TResult>

async Task<TResult> 修飾一個(gè)方法,那么這個(gè)方法要返回 await Task<TResult> 的結(jié)果。

兩種同步方式示例對(duì)比:

        public static int Test()
        {
            Task<int> task = new Task<int>(() =>
            {
                // 模擬洗衣服的時(shí)間
                int time = new Random().Next(2, 6);
                Thread.Sleep(TimeSpan.FromSeconds(time));
                return time;
            });
            task.Start();
            return task.Result;
        }
        public static async Task<int> TestAsync()
        {
            Task<int> task = new Task<int>(() =>
            {
                // 模擬洗衣服的時(shí)間
                int time = new Random().Next(2, 6);
                Thread.Sleep(TimeSpan.FromSeconds(time));
                return time;
            });
            task.Start();
            int time = await task;
            return time;
        }

同步異步?

問:async 和 await 不是跟異步方法有關(guān)嘛,為啥前面的示例使用了 await ,全部變成同步了?

問:使用 async 和 await 的方法,執(zhí)行過程到底是同步還是異步?

答:同步異步都行,要同步還是異步,全掌握在你的手上。

  • 你使用 await 去調(diào)用一個(gè)異步方法,其執(zhí)行過程就是同步。
  • 你獲取異步方法返回的 Task,就是異步。

最近筆者收到一些提問,有些讀者,使用 async 和 await 去編寫業(yè)務(wù),想著是異步,可以提升性能,實(shí)際結(jié)果還是同步,性能一點(diǎn)沒有提升。通過下面的示例,你會(huì)馬上理解應(yīng)該怎么用。

首先,在不使用 async 和 await 關(guān)鍵字的情況下,我們來編寫兩個(gè)方法,分別實(shí)現(xiàn)同步和異步的功能,兩個(gè)方法執(zhí)行的結(jié)果是一致的。

        /// <summary>
        /// 同步
        /// </summary>
        /// <returns></returns>
        public static int Test()
        {
            Task<int> task = new Task<int>(() =>
            {
                return 666;
            });
            task.Start();
            return task.Result;
        }
        
        /// <summary>
        /// 異步
        /// </summary>
        /// <returns></returns>
        public static Task<int> TestAsync()
        {
            Task<int> task = new Task<int>(() =>
            {
                return 666;
            });
            task.Start();
            return task;
        }

能不能將兩個(gè)方法合并在一起呢?想同步就同步,想異步就異步,這樣就不需要寫兩個(gè)方法了!

是可以的!通過 async 和 await 關(guān)鍵字,可以輕松實(shí)現(xiàn)!

合并后,代碼如下:

        /// <summary>
        /// 可異步可同步
        /// </summary>
        /// <returns></returns>
        public static async Task<int> TestAsync()
        {
            Task<int> task = new Task<int>(() =>
            {
                return 666;
            });
            task.Start();
            return await task;
        }

合并后,我們又應(yīng)該怎么在調(diào)用的時(shí)候,實(shí)現(xiàn)同步和異步呢?

筆者這里給出兩個(gè)示例:

        // await 使得任務(wù)同步
        public async void T1()
        {
            // 使用 await 關(guān)鍵字,代表等待執(zhí)行完成,同步
            int time = await TestAsync();
            Console.WriteLine(time);
        }

        // 直接獲得返回的 Task,實(shí)現(xiàn)異步
        public void T2()
        {
            // 獲取 Task 任務(wù)對(duì)象,后面的邏輯過程可以弄成異步
            Task<int> task = TestAsync();

            // 任務(wù)是異步在執(zhí)行,我不理會(huì)他
            // 這里可以處理其它事情,處理完畢后,再獲取執(zhí)行結(jié)果
            // 這就是異步

            Console.WriteLine(task.Result);
        }

至此,理解為什么使用了 async 和 await,執(zhí)行時(shí)還是同步了吧?

Task封裝異步任務(wù)

前面,我們都是使用了 new Task() 來創(chuàng)建任務(wù),而且微軟官網(wǎng)大多使用 Task.Run() 來編寫 async 和 await 的示例。

因此,我們可以修改前面的異步任務(wù),改成:

        /// <summary>
        /// 可異步可同步
        /// </summary>
        /// <returns></returns>
        public static async Task<int> TestAsync()
        {
            return await Task.Run<int>(() =>
            {
                return 666;
            });
        }

關(guān)于跳到 await 變異步

在百度學(xué)習(xí)異步的時(shí)候,往往會(huì)有作者說,進(jìn)入異步方法后,同步執(zhí)行代碼,碰到 await 后就是異步執(zhí)行。

當(dāng)然還有多種說法。

我們已經(jīng)學(xué)習(xí)了這么多的任務(wù)(Task)知識(shí),這一點(diǎn)十分容易解釋。

因?yàn)槭褂昧?async 和 await 關(guān)鍵字,代碼最深處,必定會(huì)出現(xiàn) Task 這個(gè)東西,Task 這個(gè)東西本來就是異步。碰到 await 出現(xiàn)異步,不是因?yàn)?await 的作用,而是因?yàn)樽畹讓佑袀€(gè) Task。

為什么出現(xiàn)一層層的 await

這是相對(duì)于提供服務(wù)者來說。因?yàn)槲乙峁┙涌诮o你使用,因此底層出現(xiàn) async、await 后,我會(huì)繼續(xù)保留方法是異步的(async),然后繼續(xù)封裝,這樣就有多層的調(diào)用結(jié)構(gòu),例如上一小節(jié)的圖。

但是如果來到了調(diào)用者這里,就不應(yīng)該還是使用 async 、await 去編寫方法,而是應(yīng)該按照實(shí)際情況同步或異步。

總結(jié)

到此這篇C#中async和await的文章就介紹到這了,更多相關(guān)C#中async和await內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Unity實(shí)現(xiàn)植物識(shí)別示例詳解

    Unity實(shí)現(xiàn)植物識(shí)別示例詳解

    這篇文章主要介紹了如何通過Unity接入百度AI實(shí)現(xiàn)植物識(shí)別,接口返回植物的名稱,并支持獲取識(shí)別結(jié)果對(duì)應(yīng)的百科信息。感興趣的可以了解一下
    2022-01-01
  • c#實(shí)現(xiàn)flv解析詳解示例

    c#實(shí)現(xiàn)flv解析詳解示例

    本文提供的解析程序簡(jiǎn)單的把FLV分解了出來,如果要做FLV的修改操作的話,可以給每個(gè)類加個(gè)toStream方法,再歷遍依次調(diào)用就可以寫回到文件里了
    2014-01-01
  • C#實(shí)現(xiàn)簡(jiǎn)單的飛行棋游戲

    C#實(shí)現(xiàn)簡(jiǎn)單的飛行棋游戲

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)簡(jiǎn)單的飛行棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • WPF利用TextBlock實(shí)現(xiàn)查找結(jié)果高亮顯示效果

    WPF利用TextBlock實(shí)現(xiàn)查找結(jié)果高亮顯示效果

    在應(yīng)用開發(fā)過程中,經(jīng)常遇到這樣的需求:通過關(guān)鍵字查找數(shù)據(jù),把帶有關(guān)鍵字的數(shù)據(jù)顯示出來,同時(shí)在結(jié)果中高亮顯示關(guān)鍵字,所以本文就來和大家介紹一下如何利用TextBlock實(shí)現(xiàn)查找結(jié)果高亮顯示效果吧
    2023-08-08
  • C#?System.Linq提供類似SQL語(yǔ)法的高效查詢操作

    C#?System.Linq提供類似SQL語(yǔ)法的高效查詢操作

    System.Linq是C#的一個(gè)命名空間,提供了LINQ(語(yǔ)言集成查詢)功能,允許開發(fā)者使用一致的查詢語(yǔ)法來處理不同類型的數(shù)據(jù)源,如數(shù)組、集合、數(shù)據(jù)庫(kù)和XML等,本文介紹C#?System.Linq提供類似SQL語(yǔ)法的高效查詢操作,感興趣的朋友一起看看吧
    2024-09-09
  • 常用C#正則表達(dá)式匯總介紹

    常用C#正則表達(dá)式匯總介紹

    c#正則表達(dá)式,用于字符串處理、表單驗(yàn)證等場(chǎng)合,實(shí)用高效?,F(xiàn)將一些常用的表達(dá)式收集于此,以備不時(shí)之需。
    2016-01-01
  • 基于XSLT調(diào)試的相關(guān)問題

    基于XSLT調(diào)試的相關(guān)問題

    本篇文章是對(duì)XSLT調(diào)試的相關(guān)問題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#?VB.NET?將Html轉(zhuǎn)為Excel

    C#?VB.NET?將Html轉(zhuǎn)為Excel

    本文介紹通過C#和VB.NET代碼展示將Html轉(zhuǎn)為Excel文檔的方法。文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定幫助,感興趣的小伙伴可以了解一下
    2022-03-03
  • 深入淺析Restful接口的兩種使用方式

    深入淺析Restful接口的兩種使用方式

    restful接口常用的兩種方式是get和post.接下來通過本文給大家介紹Restful接口的兩種使用方式,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2018-09-09
  • C#批量刪除Excel重復(fù)項(xiàng)的實(shí)現(xiàn)方法

    C#批量刪除Excel重復(fù)項(xiàng)的實(shí)現(xiàn)方法

    當(dāng)從不同來源導(dǎo)入Excel數(shù)據(jù)時(shí),可能存在重復(fù)的記錄,為了確保數(shù)據(jù)的準(zhǔn)確性,通常需要?jiǎng)h除這些重復(fù)的行,本文將提供一個(gè)使用C# 快速查找并刪除Excel重復(fù)項(xiàng)的免費(fèi)解決方案,需要的朋友可以參考下
    2024-04-04

最新評(píng)論