網(wǎng)站首頁 編程語言 正文
大概理解
查了一個小時的資料:async和await
發(fā)現(xiàn)這個大神的解釋一針見血,深得我心!以最簡單的例子,解釋了async和await。妙~~~
大多情況下,分開才能體現(xiàn)async和await的價值!
?但,await 并沒有這么簡單。
深入分析
await和Wait()的區(qū)別
接下來繼續(xù)往下看:
await Task.Delay(3000);? 和Task.Delay(3000).Wait();? ?有沒有區(qū)別?
上代碼:
using System.Diagnostics;
namespace await_async2
{
internal class Program
{
static public void TestWait()
{
var t = Task.Factory.StartNew(() =>
{
Console.WriteLine("Start");
Task.Delay(3000).Wait();
Console.WriteLine("Done");
});
t.Wait();
Console.WriteLine("All done");
}
static public void TestWait2()
{
var t = Task.Factory.StartNew(async () =>
{
Console.WriteLine("Start");
await Task.Delay(3000);
Console.WriteLine("Done");
});
t.Wait();
Console.WriteLine("All done");
}
static public void TestWait3()
{
var t = Task.Run(async () =>
{
Console.WriteLine("Start");
await Task.Delay(3000);
Console.WriteLine("Done");
});
t.Wait();
Console.WriteLine("All done");
}
static void Main(string[] args)
{
TestWait2();
//避免程序提前退出,導致一些現(xiàn)象看不到
Task.Delay(5000).Wait();
}
}
}
首先,強調一下,最后一句 Task.Delay(5000).Wait(); 是必須的,不然,程序提前退出,導致一些現(xiàn)象看不到,從而蒙蔽了我們。
第1段代碼TestWait執(zhí)行效果,如下:
第2段代碼TestWait2執(zhí)行效果,如下:
第3段代碼TestWait3執(zhí)行效果,如下:
現(xiàn)在給出結論:
Task.Delay(3000).Wait(); 這個就是同步等。
await Task.Delay(3000); 因為沒有分開來寫(見第一張圖),所以基本和同步等沒有區(qū)別。
但是如果 await Task.Delay(3000); 是寫到:Task.Factory.StartNew里面的
static public void TestWait2()
{
var t = Task.Factory.StartNew(async () =>
{
Console.WriteLine("Start");
await Task.Delay(3000);
Console.WriteLine("Done");
});
t.Wait();
Console.WriteLine("All done");
}
那這個效果不一樣了,他們執(zhí)行的權限丟出去了有點像python里的yeild,來看下程序的執(zhí)行順序:
?這里就看出了:await Task.Delay(3000);? 和Task.Delay(3000).Wait(); 的區(qū)別了。(但是這種情況如果在道Task.Run里面就體現(xiàn)不出來!)
然后,我有簡單做了一個實驗:
這就更明了了,?await Task.Delay(3000); 就像設置了一個回調,一旦三秒時間一到,程序的指針就會回到await Task.Delay(3000);后面的位置,直到函數(shù)執(zhí)行結束。再回到之前的位置。這就是所謂的用同步的方式寫異步的代碼吧。
但是,為啥在Task.Factory.StartNew才會體現(xiàn)出來,這個我就不清楚了,請各位大佬指點一下。
去掉Task.Run的Wait
再來對比一下,下面這兩個函數(shù):
static public void TestWait8()
{
var t = Task.Run(async () =>
{
Console.WriteLine("Start");
await Task.Delay(3000);
Console.WriteLine("Done");
});
Console.WriteLine("All done");
}
static public void TestWait8_5()
{
var t = Task.Factory.StartNew(async () =>
{
Console.WriteLine("Start");
await Task.Delay(3000);
Console.WriteLine("Done");
});
t.Wait();
Console.WriteLine("All done");
}
先看第一個TestWait8,由于Task.Run不再調用?t.Wait(),Task.Run內(nèi)部這個線程和主線程是并行的關系。程序指針會在兩個線程中來回切換。如果一方中寫了await xxx,那程序指針必然跳到另一個線程。直達await結束才可能返回。 這種情形是比較多的。此時await能節(jié)省大量等待時間(比如IO操作時間),充分利用等待時間。
此時 Console.WriteLine("All done");會最先被打印出來。
再看第二個TestWait8_5(其實就是回顧一下),當程序執(zhí)行到t.Wait()時,程序不會繼續(xù)向下了,(此時因為有t.Wait()的存在,所以子線程其實是優(yōu)先于主線程的)而是進入到子線程的內(nèi)部進程,試圖將這個線程執(zhí)行完,但是再線程里面遇到又遇到await Task.Delay(3000);此時程序指針不會再這里死等,程序指針又跳回主線程繼續(xù)執(zhí)行,直到三秒到了之后就會回到子線程,子線程執(zhí)行完了之后,再回到主線程。
但是如果吧TestWait8_5 中? ? Task.Factory.StartNew 換成?Task.Run ,那么前面的過程一樣,只是執(zhí)行到await Task.Delay(3000);時候,此時會死等,不會跳到主線程,而是一定等到這個子線程完結,再回主線程。
小結
總結一下就是,遇到await 一定會等,至于程序指針是先跳到其他線程,還是在此線程死等,就看你的線程函數(shù)這么寫的了。
其他
.Await();
最后,還有個:Task.Delay(3000).Await();
這個是prsim對Task寫的的一個拓展方法(避免在主線程調用時,阻塞UI):
總結
原文鏈接:https://blog.csdn.net/songhuangong123/article/details/127627231
相關推薦
- 2022-05-06 python使用xlrd模塊讀取excel的方法實例_python
- 2022-06-17 使用Python解決常見格式圖像讀取nii,dicom,mhd_python
- 2022-04-16 Python實現(xiàn)杰卡德距離以及環(huán)比算法講解_python
- 2022-07-09 Android中Intent的簡單使用和與Bundle的關系
- 2022-06-26 詳解Go語言中的作用域和變量隱藏_Golang
- 2024-03-21 微信支付的簽名算法
- 2022-03-28 Easyx實現(xiàn)窗口自動碰撞的小球_C 語言
- 2022-09-21 Python+pandas編寫命令行腳本操作excel的tips詳情_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支