In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how C # optimizes the time of making breakfast through synchronization and asynchronism". In the operation of practical cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Overview
The plan of the day is in the morning, and breakfast every day is also essential, but in order to save time, many people simply make do or skip breakfast at all, which is undoubtedly unreasonable for personal health and work efficiency. so how do you make breakfast? How can you save the time of making breakfast? With a simple example, this paper briefly describes how to make a breakfast and how to optimize the time of making breakfast. For learning and sharing only, if there are any deficiencies, please correct them.
Under normal circumstances, making breakfast can be divided into the following steps:
Pour a cup of coffee.
Heat the pan and fry two eggs.
Fry three slices of bacon.
Bake two slices of bread.
Add butter and jam to the toast.
Pour a glass of orange juice.
Make breakfast synchronously
To program according to the above steps, you need to write the following program to make a breakfast:
/ private void btnBreakfast_Click (object sender, EventArgs e) {this.txtInfo.Clear (); Stopwatch watch = Stopwatch.StartNew (); watch.Start (); / / 1. Pour a cup of coffee. String cup = PourCoffee (); PrintInfo ("coffee is ready"); / / 2. Heat the pan and fry two eggs. String eggs = FryEggs (2); PrintInfo ("eggs are fried"); / / 3. Fry three slices of bacon. String bacon = FryBacon (3); PrintInfo ("bacon is ready"); / / 4. Bake two slices of bread. String toast = ToastBread (2) / / 5. Add butter and jam to the toast. ApplyButter (toast); ApplyJam (toast); PrintInfo ("the bread is ready"); / / 6. Pour a glass of orange juice. String oj = PourOJ (); PrintInfo ("orange juice is poured"); PrintInfo ("breakfast is ready!"); watch.Stop (); TimeSpan time = watch.Elapsed; PrintInfo ("total elapsed time: {0} seconds", time.TotalSeconds.ToString ("0.00") } / / pour a cup of coffee / private string PourCoffee () {PrintInfo ("making coffee..."); return "coffee" / private void ApplyJam (string toast) = > PrintInfo ("spread jam on bread"); / butter / private void ApplyButter (string toast) = > PrintInfo ("butter bread") / private string ToastBread (int slices) {for (int slice = 0; slice)
< slices; slice++) { PrintInfo("往烤箱里面放面包"); } PrintInfo("开始烤..."); Task.Delay(3000).Wait(); PrintInfo("从烤箱取出面包"); return "烤面包"; } /// /// 煎培根 /// /// /// private string FryBacon(int slices) { PrintInfo($"放 {slices} 片培根在平底锅"); PrintInfo("煎第一片培根..."); Task.Delay(3000).Wait(); for (int slice = 0; slice < slices; slice++) { PrintInfo("翻转培根"); } PrintInfo("煎第二片培根..."); Task.Delay(3000).Wait(); PrintInfo("把培根放盘子里"); return "煎培根"; } /// /// 煎鸡蛋 /// /// /// private string FryEggs(int howMany) { PrintInfo("加热平底锅..."); Task.Delay(3000).Wait(); PrintInfo($"磕开 {howMany} 个鸡蛋"); PrintInfo("煎鸡蛋 ..."); Task.Delay(3000).Wait(); PrintInfo("鸡蛋放盘子里"); return "煎鸡蛋"; } /// /// 倒橙汁 /// /// private string PourOJ() { PrintInfo("倒一杯橙汁"); return "橙汁"; }同步做早餐示例 通过运行示例,发现采用同步方式进行编程,做一份早餐,共计15秒钟,且在此15秒钟时间内,程序处于【卡住】状态,无法进行其他操作。如下所示:Sketch diagram of making breakfast at the same time
To make breakfast synchronously, one is done, and then the next, executed sequentially, as shown below:
Why is the synchronization mode [stuck]?
Because in the program process, there will be a main thread that responds to the user's actions, and in synchronous mode, the breakfast maker and the front-end page are in the main thread, so when you start cooking breakfast, you can't respond to other operations. This is the realm of "two ears do not hear anything out of the window, but only read the books of sages". However, if you keep users waiting for a long time, it will make the user experience very unfriendly. For example, Liu Xuande looked at the thatched cottage three times, under the heavy snow, Zhuge Liang took a nap in the cottage, Liu Guanzhang was quiet in the heavy snow, and so on. I would like to ask how many people will have Xuande's patience, not to mention the program is not Zhuge Liang, users do not have Xuande's patience!
Make breakfast asynchronously
The above code demonstrates the incorrect practice of constructing synchronous code to perform asynchronous operations. As the name implies, this code will prevent the thread executing this code from performing any other actions. This code will not be interrupted while any task is in progress. Just like you put the bread in the toaster and stare at the toaster. You will ignore anyone who talks to you until the bread pops up. What can I do to avoid thread blocking? The answer is asynchronous. The await keyword provides a non-blocking way to start a task and then continue to execute when the task is complete.
First update the code to make breakfast asynchronously for time-consuming programs, as follows:
Private async void btnBreakfastAsync_Click (object sender, EventArgs e) {this.txtInfo.Clear (); Stopwatch watch = Stopwatch.StartNew (); watch.Start (); / / 1. Pour a cup of coffee. String cup = PourCoffee (); PrintInfo ("coffee is ready"); / / 2. Heat the pan and fry two eggs. / / Task eggs = FryEggsAsync (2); string eggs = await FryEggsAsync (2); PrintInfo ("eggs are ready"); / / 3. Fry three slices of bacon. String bacon = await FryBaconAsync (3); PrintInfo ("bacon is ready"); / / 4. Bake two slices of bread. String toast = await ToastBreadAsync (2) / / 5. Add butter and jam to the toast. ApplyButter (toast); ApplyJam (toast); PrintInfo ("the bread is ready"); / / 6. Pour a glass of orange juice. String oj = PourOJ (); PrintInfo ("orange juice is poured"); PrintInfo ("breakfast is ready!"); watch.Stop (); TimeSpan time = watch.Elapsed; PrintInfo ("total elapsed time: {0} seconds", time.TotalSeconds.ToString ("0.00") } / Asynchronous toast / private async Task ToastBreadAsync (int slices) {for (int slice = 0; slice)
< slices; slice++) { PrintInfo("往烤箱里面放面包"); } PrintInfo("开始烤..."); await Task.Delay(3000); PrintInfo("从烤箱取出面包"); return "烤面包"; } /// /// 异步煎培根 /// /// /// private async Task FryBaconAsync(int slices) { PrintInfo($"放 {slices} 片培根在平底锅"); PrintInfo("煎第一片培根..."); await Task.Delay(3000); for (int slice = 0; slice < slices; slice++) { PrintInfo("翻转培根"); } PrintInfo("煎第二片培根..."); await Task.Delay(3000); PrintInfo("把培根放盘子里"); return "煎培根"; } /// /// 异步煎鸡蛋 /// /// /// private async Task FryEggsAsync(int howMany) { PrintInfo("加热平底锅..."); await Task.Delay(3000); PrintInfo($"磕开 {howMany} 个鸡蛋"); PrintInfo("煎鸡蛋 ..."); await Task.Delay(3000); PrintInfo("鸡蛋放盘子里"); return "煎鸡蛋"; } 注意:通过测试发现,异步方式和同步方式的执行时间一致,所以采用异步方式并不会缩短时间,但是程序已不再阻塞,可以同时响应用户的其他请求。 优化异步做早餐 通过上述异步方式,虽然优化了程序,不再阻塞,但是时间并没有缩短,那么要如何优化程序来缩短时间,以便早早的吃上可口的早餐呢?答案就是在开始一个任务后,在等待任务完成时,可以继续进行准备其他的任务。 你也几乎将在同一时间完成所有工作。 你将吃到一顿热气腾腾的早餐。通过合并任务和调整任务的顺序,将大大节约任务的完成时间,如下所示: /// /// 优化异步做早餐 /// /// /// private async void btnBreakfast2_Click(object sender, EventArgs e) { this.txtInfo.Clear(); Stopwatch watch = Stopwatch.StartNew(); watch.Start(); //1. 倒一杯咖啡。 string cup = PourCoffee(); PrintInfo("咖啡冲好了"); //2. 加热平底锅,然后煎两个鸡蛋。 Task eggsTask = FryEggsAsync(2); //3. 煎三片培根。 Task baconTask = FryBaconAsync(3); //4.5合起来 烤面包,抹果酱,黄油 Task toastTask = MakeToastWithButterAndJamAsync(2); string eggs = await eggsTask; PrintInfo("鸡蛋煎好了"); string bacon = await baconTask; PrintInfo("培根煎好了"); string toast = await toastTask; PrintInfo("面包烤好了"); //6. 倒一杯橙汁。 string oj = PourOJ(); PrintInfo("橙汁倒好了"); PrintInfo("早餐准备完毕!"); watch.Stop(); TimeSpan time = watch.Elapsed; PrintInfo(string.Format("总运行时间为:{0}秒", time.TotalSeconds.ToString("0.00"))); } /// /// 组合任务 /// /// /// private async Task MakeToastWithButterAndJamAsync(int number) { var toast = await ToastBreadAsync(number); ApplyButter(toast); ApplyJam(toast); return toast; } 在本例中,合并了【烤面包+抹果酱+抹黄油】为一个任务,这样是烤面包的同时,可以煎鸡蛋,煎培根,三项耗时任务同时执行。在三个任务都完成是,早餐也就做好了,示例如下所示: 通过以上优化示例发现,通过合并任务和调整顺序,做一份早餐,需要6.06秒。 优化异步早餐示意图 优化后的异步做早餐,由于一些任务并发运行,因此节约了时间。示意图如下所示: 异步异常 上述示例假定所有的任务都可以正常完成,那么如果某一个任务执行过程中发生了异常,要如何捕获呢?答案是:当任务无法成功完成时,它们将引发异常。 当启动的任务为 awaited 时,客户端代码可捕获这些异常。 例如当烤面包的时候,烤箱突然着火了,如何处理异常呢?代码如下所示: private async void btnBreakfastAsync3_Click(object sender, EventArgs e) { try { this.txtInfo.Clear(); Stopwatch watch = Stopwatch.StartNew(); watch.Start(); //1. 倒一杯咖啡。 string cup = PourCoffee(); PrintInfo("咖啡冲好了"); //2. 加热平底锅,然后煎两个鸡蛋。 Task eggsTask = FryEggsAsync(2); //3. 煎三片培根。 Task baconTask = FryBaconAsync(3); //4.5合起来 烤面包,抹果酱,黄油 Task toastTask = MakeToastWithButterAndJamAsyncEx(2); string eggs = await eggsTask; PrintInfo("鸡蛋煎好了"); string bacon = await baconTask; PrintInfo("培根煎好了"); string toast = await toastTask; PrintInfo("面包烤好了"); //6. 倒一杯橙汁。 string oj = PourOJ(); PrintInfo("橙汁倒好了"); PrintInfo("早餐准备完毕!"); watch.Stop(); TimeSpan time = watch.Elapsed; PrintInfo(string.Format("总运行时间为:{0}秒", time.TotalSeconds.ToString("0.00"))); } catch (AggregateException ex) { PrintInfo("线程内部异常"); PrintInfo(ex.StackTrace); } catch (Exception ex) { PrintInfo("其他异常"); PrintInfo(ex.Message); } } /// /// 组合任务 /// /// /// private async Task MakeToastWithButterAndJamAsyncEx(int number) { var toast = await ToastBreadAsyncEx(number); ApplyButter(toast); ApplyJam(toast); return toast; } /// /// 异步烤面包异常 /// /// /// private async Task ToastBreadAsyncEx(int slices) { for (int slice = 0; slice < slices; slice++) { PrintInfo("往烤箱里面放面包"); } PrintInfo("开始烤..."); await Task.Delay(2000); PrintInfo("着火了! 面包糊了!"); int a = 1, b = 0; int i = a / b;//制造一个异常 //throw new InvalidOperationException("烤箱着火了!"); await Task.Delay(1000); PrintInfo("从烤箱取出面包"); return "烤面包"; }异步任务异常示例 请注意,从烤面包机着火到发现异常,有相当多的任务要完成。 当异步运行的任务引发异常时,该任务出错。 Task 对象包含 Task.Exception 属性中引发的异常。 出错的任务在等待时引发异常。 需要理解两个重要机制:异常在出错的任务中的存储方式,以及在代码等待出错的任务时解包并重新引发异常的方式。 当异步运行的代码引发异常时,该异常存储在 Task 中。 Task.Exception 属性为 System.AggregateException,因为异步工作期间可能会引发多个异常。 引发的任何异常都将添加到 AggregateException.InnerExceptions 集合中。 如果该 Exception 属性为 NULL,则将创建一个新的 AggregateException 且引发的异常是该集合中的第一项。 对于出错的任务,最常见的情况是 Exception 属性只包含一个异常。 当代码 awaits 出错的任务时,将重新引发 AggregateException.InnerExceptions 集合中的第一个异常。 因此,此示例的输出显示 InvalidOperationException 而不是 AggregateException。 提取第一个内部异常使得使用异步方法与使用其对应的同步方法尽可能相似。 当你的场景可能生成多个异常时,可在代码中检查 Exception 属性。 高效的等待 通过以上示例,需要等待很多任务完成,然后早餐才算做好,那么如何才能高效优雅的等待呢?可以通过使用 Task 类的方法改进上述代码末尾的一系列 await 语句。其中一个 API 是 WhenAll,它将返回一个其参数列表中的所有任务都已完成时才完成的 Task,如下所示: private async void btnBreakfastAsync4_Click(object sender, EventArgs e) { this.txtInfo.Clear(); Stopwatch watch = Stopwatch.StartNew(); watch.Start(); //1. 倒一杯咖啡。 string cup = PourCoffee(); PrintInfo("咖啡冲好了"); //2. 加热平底锅,然后煎两个鸡蛋。 Task eggsTask = FryEggsAsync(2); //3. 煎三片培根。 Task baconTask = FryBaconAsync(3); //4.5合起来 烤面包,抹果酱,黄油 Task toastTask = MakeToastWithButterAndJamAsync(2); //等待任务完成 await Task.WhenAll(eggsTask, baconTask, toastTask); PrintInfo("鸡蛋煎好了"); PrintInfo("培根煎好了"); PrintInfo("面包烤好了"); //6. 倒一杯橙汁。 string oj = PourOJ(); PrintInfo("橙汁倒好了"); PrintInfo("早餐准备完毕!"); watch.Stop(); TimeSpan time = watch.Elapsed; PrintInfo(string.Format("总运行时间为:{0}秒", time.TotalSeconds.ToString("0.00"))); } 另一种选择是使用 WhenAny,它将返回一个当其参数完成时才完成的 Task。如下所示: private async void btnBreakfastAsync5_Click(object sender, EventArgs e) { this.txtInfo.Clear(); Stopwatch watch = Stopwatch.StartNew(); watch.Start(); //1. 倒一杯咖啡。 string cup = PourCoffee(); PrintInfo("咖啡冲好了"); //2. 加热平底锅,然后煎两个鸡蛋。 Task eggsTask = FryEggsAsync(2); //3. 煎三片培根。 Task baconTask = FryBaconAsync(3); //4.5合起来 烤面包,抹果酱,黄油 Task toastTask = MakeToastWithButterAndJamAsync(2); //等待任务完成 var breakfastTasks = new List { eggsTask, baconTask, toastTask }; while (breakfastTasks.Count >0) {Task finishedTask = await Task.WhenAny (breakfastTasks); if (finishedTask = = eggsTask) {PrintInfo ("eggs fried");} else if (finishedTask = = baconTask) {PrintInfo ("bacon fried") } else if (finishedTask = = toastTask) {PrintInfo ("the bread is baked");} breakfastTasks.Remove (finishedTask);} / / 6. Pour a glass of orange juice. String oj = PourOJ (); PrintInfo ("orange juice is poured"); PrintInfo ("breakfast is ready!"); watch.Stop (); TimeSpan time = watch.Elapsed; PrintInfo ("total elapsed time: {0} seconds", time.TotalSeconds.ToString ("0.00") } this is the content of "how to optimize the time for making breakfast through synchronization and asynchronism". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.