方城企業(yè)網(wǎng)站制作哪家好英語(yǔ)培訓(xùn)
C#中的同步和異步《一》
以下理解借鑒博客:借鑒博客地址1
異步編程(Asynchronous)
允許任務(wù)在后臺(tái)執(zhí)行,而不會(huì)阻塞調(diào)用線程。C#使用async和await關(guān)鍵字
async Task AsynchronousMethod()
{// 等待異步操作完成await Task.Delay(1000); // 模擬耗時(shí)操作Console.WriteLine("AsynchronousMethod 完成");
}
串行:
任務(wù)按照順序一個(gè)接一個(gè)地執(zhí)行,這在單線程程序中是自然的
// 同步串行
void Task1()
{Console.WriteLine("Task 1 is running");
}void Task2()
{Console.WriteLine("Task 2 is running");
}Task1();
Task2();// 異步串行
async Task Task1Async()
{Console.WriteLine("Task 1 is running");await Task.Delay(1000); // 模擬異步操作
}async Task Task2Async()
{Console.WriteLine("Task 2 is running");await Task.Delay(1000); // 模擬異步操作
}async Task MainAsync()
{await Task1Async();await Task2Async();
}MainAsync().GetAwaiter().GetResult(); // 運(yùn)行異步方法
并行:(Parallel)
允許多個(gè)任務(wù)同時(shí)執(zhí)行,通常利用多核處理器的能力。在C#中,Parallel.For、Parallel.ForEach和Parallel.Invoke等API用于并行執(zhí)行。
using System.Threading.Tasks;void Task1()
{Console.WriteLine("Task 1 is running");
}void Task2()
{Console.WriteLine("Task 2 is running");
}Parallel.Invoke(() => Task1(), () => Task2());
Parallel.For(0, 10, i =>
{Console.WriteLine($"并行任務(wù) {i} 開始");Thread.Sleep(100); // 模擬耗時(shí)操作Console.WriteLine($"并行任務(wù) {i} 完成");
});
并發(fā)(Concurrency):
并發(fā)是并行和串行在更廣泛意義上的結(jié)合。它指的是多個(gè)任務(wù)同時(shí)或幾乎同時(shí)執(zhí)行,但不一定在物理上并行
using System.Threading;void Task1()
{Console.WriteLine("Task 1 is running");
}void Task2()
{Console.WriteLine("Task 2 is running");
}Thread t1 = new Thread(new ThreadStart(Task1));
Thread t2 = new Thread(new ThreadStart(Task2));t1.Start();
t2.Start();t1.Join();
t2.Join();
死鎖(Deadlock)
當(dāng)兩個(gè)或多個(gè)線程相互等待對(duì)方釋放資源時(shí),就會(huì)發(fā)生死鎖
避免死鎖的策略:1.確保所有線程以相同的順序獲取資源。2.使用鎖超時(shí)機(jī)制。3.避免嵌套鎖。4.使用更高級(jí)的并發(fā)控制機(jī)制,如信號(hào)量、事件或Concurrent集合。
以下理解借鑒博客:借鑒博客2
通過某種機(jī)制,讓程序在等著IO的過程中,繼續(xù)做點(diǎn)別的事,等IO的過程完成了,再回來處理IO的內(nèi)容 --異步編程模型
C#中,異步編程,一個(gè)核心是指Task和Task對(duì)象,而兩個(gè)關(guān)鍵字,就是async和await。
?在遇到await關(guān)鍵字之后,系統(tǒng)做了以下工作:
異步方法將被掛起
將控制權(quán)返回給調(diào)用者
使用線程池中的線程(而非額外創(chuàng)建新的線程)來計(jì)算await表達(dá)式的結(jié)果,所以await不會(huì)造成程序的阻塞
完成對(duì)await表達(dá)式的計(jì)算之后,若await表達(dá)式后面還有代碼則由執(zhí)行await表達(dá)式的線程(不是調(diào)用方所在的線程)繼續(xù)執(zhí)行這些代碼
?定義一個(gè)異步方法應(yīng)滿足以下幾點(diǎn):
使用async關(guān)鍵字來修飾方法
在異步方法中使用await關(guān)鍵字(不使用編譯器會(huì)給出警告但不報(bào)錯(cuò)),否則異步方法會(huì)以同步方式執(zhí)行
盡量不使用void作為返回類型,若希望異步方法返回void類型,請(qǐng)使用Task
異步方法名稱以Async結(jié)尾
異步方法中不能聲明使用ref或out關(guān)鍵字修飾的變量
模式:
//定義
async Task function()
{/* your code here */
}
//調(diào)用
await function();
?問題點(diǎn):async和await的配對(duì)
在異步編程的規(guī)范中,async修飾的方法,僅僅表示這個(gè)方法在內(nèi)部有可能采用異步的方式執(zhí)行,CPU在執(zhí)行這個(gè)方法時(shí),會(huì)放到一個(gè)新的線程中執(zhí)行。
那這個(gè)方法,最終是否采用異步執(zhí)行,不決定于是否用await方式調(diào)用這個(gè)方法,而決定于這個(gè)方法內(nèi)部,是否有await方式的調(diào)用。
await是什么意思?
提及Wait:Wait就是等待,異步有一個(gè)核心,是Task。而Task有一個(gè)方法,就是Wait,寫法是Task.Wait()。所以,很多人把這個(gè)Wait和await混為一談,這是錯(cuò)的。
C#里,Task不是專為異步準(zhǔn)備的,它表達(dá)的是一個(gè)線程,是工作在線程池里的一個(gè)線程。異步是線程的一種應(yīng)用,多線程也是線程的一種應(yīng)用。Wait,以及Status、IsCanceled、IsCompleted、IsFaulted等等,是給多線程準(zhǔn)備的方法,跟異步?jīng)]有半毛錢關(guān)系。Task.Wait()是一個(gè)同步方法,用于多線程中阻塞等待。
在異步中,await表達(dá)的意思是:當(dāng)前線程/方法中,await引導(dǎo)的方法出結(jié)果前,跳出當(dāng)前線程/方法,從調(diào)用當(dāng)前線程/方法的位置,去執(zhí)行其它可能執(zhí)行的線程/方法,并在引導(dǎo)的方法出結(jié)果后,把運(yùn)行點(diǎn)拉回到當(dāng)前位置繼續(xù)執(zhí)行;直到遇到下一個(gè)await,或線程/方法完成返回,跳回去剛才外部最后執(zhí)行的位置繼續(xù)執(zhí)行。
await在控制異步的執(zhí)行次序。那為什么要用等待這么個(gè)詞呢?是因?yàn)閍wait確實(shí)有等待結(jié)果的含義
await的第二層意思:等待拿到結(jié)果:我們需要使用func1方法的返回值。我們可以提前去執(zhí)行這個(gè)方法,而不急于拿到方法的返回值,直到我們需要使用時(shí),再用await去獲取到這個(gè)返回值去使用。
這才是異步對(duì)于我們真正的用處。對(duì)于一些耗時(shí)的IO或類似的操作,我們可以提前調(diào)用,讓程序可以利用執(zhí)行過程中的空閑時(shí)間來完成這個(gè)操作。等到我們需要這個(gè)操作的結(jié)果用于后續(xù)的執(zhí)行時(shí),我們await這個(gè)結(jié)果。這時(shí)候,如果await的方法已經(jīng)執(zhí)行完成,那我們可以馬上得到結(jié)果;如果沒有完成,則程序?qū)⒗^續(xù)執(zhí)行這個(gè)方法直到得到結(jié)果。
static async Task Main(string[] args)
{Console.WriteLine("Async proccess - start");Console.WriteLine("Async proccess - enter Func1");Task<int> f = func1();Console.WriteLine("Async proccess - out Func1");Console.WriteLine("Async proccess - done");int result = await f;Console.WriteLine("Main proccess - done");Console.ReadKey();
}private static async Task<int> func1()
{Console.WriteLine("Func1 proccess - start");await Task.Run(() => Thread.Sleep(1000));Console.WriteLine("Func1 proccess - end");return 5;
}
同步方法中調(diào)用異步:
func1().GetAwaiter().GetResult();