欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

【C#】async,await執行流看不懂?看完這篇以后再也不會了

admin
2023年9月28日 9:21 本文熱度 565

昨天有朋友在公眾號發消息說看不懂await,async執行流,其實看不懂太正常了,因為你沒經過社會的毒打,沒吃過牢飯就不知道自由有多重要,沒生過病就不知道健康有多重要,沒用過ContinueWith就不知道await,async有多重要,下面我舉兩個案例佐證一下?

一:案例一 【嵌套下的異步】

寫了這么多年的程序,相信大家都知道連接數據庫少不了這幾個對象,DbConnection,DbCommand,DbDataReader等等。。先來看看ContinueWith在連接數據庫時嵌套過深的尷尬。

1. NetFramework 4.0之前的寫法

這個時期的代碼沒有什么好說的,都是程式代碼,一擼到底,簡潔明了。

        public static int SyncGetCount()
       
{
           using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))
           {
               connection.Open();
               using (var command = connection.createCommand())
               {
                   command.CommandText = "select count(1) from messages";

                   var count = command.executeScalar();

                   Console.WriteLine($"記錄條數:{count}");

                   return Convert.ToInt32(count);
               }
           }
       }

-------- output -------------

記錄條數:75896

2. NetFramework 4.0下ContinueWith的寫法

當年異步和并發編程概念特別火,火熱度參考現在的直播帶貨,這個時期的C#率先使用新的Task一網兜,在數據庫操作的幾大類中開始有了Async結尾的方法,如OpenAsync,executeScalarAsync,ReadAsync 等等,但遺憾的是那時寫異步,只能像下面這樣寫。

        public static Task<object> ContinueWithGetCount()
       {
           var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;");

           var task = connection.OpenAsync().ContinueWith(t1 =>
            {
                var command = connection.createCommand();

                command.CommandText = "select count(1) from messages";

                return command.executeScalarAsync().ContinueWith(t2 =>
                                                                 {
                                                                     command.Dispose();
                                                                     connection.Dispose();

                                                                     Console.WriteLine($"記錄條數:{t2.Result}");

                                                                     return t2.Result;
                                                                 });
            }).Unwrap();


           return task;
       }

-------- output -------------

記錄條數:75896

相比同步代碼,這異步代碼寫的是不是很憋屈,為了應對漸進式的Async方法,我不得不進行ContinueWith的深層嵌套,如果Async更多,那對可讀性將是毀滅性的打擊,這就是所謂的回調地獄。

3. NetFramework 4.5 下 await,async的寫法

寫到這里讓我想起了邢老大的那本自傳書《左手夢想,右手療傷》,這苦這心酸只有真正經歷過的人才會懂,沒有人能夠隨隨便便成功,接下來大家的期望就是如何做到有同步式的代碼又有異步功效,魚和熊掌我都要,當然是可以的,看看如何用await,async進行改造。


       public static async Task<int> AsyncGetCount()
       {
           using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))
           {
               await connection.OpenAsync();
               using (var command = connection.createCommand())
               {
                   command.CommandText = "select count(1) from messages";

                   var count = await command.executeScalarAsync();

                   Console.WriteLine($"記錄條數:{count}");

                   return Convert.ToInt32(count);
               }
           }
       }

-------- output -------------

記錄條數:75896

上面這代碼太簡潔了,眼花的朋友還以為是同步代碼呢?改造的地方也僅僅是方法簽名處加上一個async,異步方法前加上await,相當于痛苦版的ContinueWith。

二:案例二 【循環下的異步】

上一個案例只是使用executeScalarAsync從數據庫中讀取一個值來得到表中的記錄數,在業務開發中更多的是使用executeReader從數據庫中獲取批量記錄,這個就涉及到了如何在循環中使用異步,想想就太苦難了(┬_┬)。

1. NetFramework 4.0之前的寫法

這里我從messages表中讀取5條記錄,然后輸出到控制臺,詳細代碼如下:


       public static List<string> SyncGetMessageList()
       {
           var messageList = new List<string>();
           using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))
           {
               connection.Open();
               using (var command = connection.createCommand())
               {
                   command.CommandText = "select message from messages limit 5;";
                   using (var reader = command.executeReader())
                   {
                       while (reader.Read())
                       {
                           messageList.Add(reader.GetString("message"));
                       }
                   }
               }
           }
           messageList.ForEach(Console.WriteLine);
           return messageList;
       }

------------- output ----------------

你需要忘記失去的,感激擁有的,和期待將至的。
以前的找不到了。
對于編譯錯誤,刪除Pods文件夾然后重新pod install已經成為經驗。次。
Hello,Is there anyone here?
放松心情

2. NetFramework 4.0下ContinueWith的寫法

要想用ContinueWith完成這功能,最簡單有效的辦法就是使用遞歸,用遞歸的方式把若干個ContinueWith串聯起來,而要用遞歸的話還要單獨定義一個方法,寫的有點亂,大家將就著看吧。

    public class Program
   {

       public static void Main(string[] args)
       
{
           var task = ContinueWithAsyncGetMessageList();

           task.Result.ForEach(Console.WriteLine);

           Console.Read();
       }

       public static Task<List<string>> ContinueWithAsyncGetMessageList()
       {
           var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;");

           var task = connection.OpenAsync().ContinueWith(t1 =>
            {
                var messageList = new List<string>();

                var command = connection.createCommand();

                command.CommandText = "select message from messages limit 5;";

                return command.executeReaderAsync().ContinueWith(t2 =>
                {
                    var reader = (MySqlDataReader)t2.Result;
                    return GetMessageList(reader, messageList).ContinueWith(t3 =>
                    {
                        reader.Dispose();
                        command.Dispose();
                        connection.Dispose();
                    });
                }).Unwrap().ContinueWith(t3 => messageList);

            }).Unwrap();

           return task;
       }

       /// <summary>
       /// 采用遞歸處理循環
       /// </summary>
       /// <param name="reader"></param>
       /// <param name="messageList"></param>
       /// <returns></returns>
       public static Task<List<string>> GetMessageList(MySqlDataReader reader, List<string> messageList)
       {
           var task = reader.ReadAsync().ContinueWith(t =>
             {
                 if (t.Result)
                 {
                     var massage = reader.GetString("message");
                     messageList.Add(massage);
                     return GetMessageList(reader, messageList);
                 }
                 else
                 {
                     return Task.fromResult(new List<string>());
                 }
             }).Unwrap();

           return task;
       }
   }

------------ output ----------------
你需要忘記失去的,感激擁有的,和期待將至的。
以前的找不到了。
對于編譯錯誤,刪除Pods文件夾然后重新pod install已經成為經驗。次。
Hello,Is there anyone here?
放松心情

在遞歸下探的過程中把messageList集合給填滿了,而后將messageList返回給調用端即可,如果沒看明白,我畫一張圖吧!

3. NetFramework 4.5 下 await,async的寫法

😄,剛剛是不是噩夢般經歷,救世主來啦,還是要魚和熊掌一起兼得。


       public static async Task<List<string>> AsyncGetMessageList()
       {
           var messageList = new List<string>();
           using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))
           {
               await connection.OpenAsync();
               using (var command = connection.createCommand())
               {
                   command.CommandText = "select message from messages limit 5;";
                   using (var reader = await command.executeReaderAsync())
                   {
                       while (await reader.ReadAsync())
                       {
                           messageList.Add(reader["message"].ToString());
                       }
                   }
               }
           }
           return messageList;
       }

------------ output ----------------
你需要忘記失去的,感激擁有的,和期待將至的。
以前的找不到了。
對于編譯錯誤,刪除Pods文件夾然后重新pod install已經成為經驗。次。
Hello,Is there anyone here?
放松心情

天底下還有如此簡潔的代碼就可以實現ContinueWith那種垃圾般代碼所實現的功能,我都想仰天長嘯,我太難了。

三:總結

還是那句話,你沒有被傷過,永遠不會體會到那種刻骨銘心的痛。



該文章在 2023/9/28 9:21:24 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved