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