根據代碼示例來學習,編程
建立一個函數來模擬時間消耗的方法,此處爲GetSomeThing
函數。併發
要使用異步編程,須要使用一個async修飾的方法來包裝調用GetSomeThing
函數,此函數的返回值爲Task類型,該類型表示進行並行運算的任務引用。此處示例爲ConsumeManyTime
函數。dom
TestOne()
函數中的代碼,其實就是直接調用第二步中的函數ConsumeManyTime()
;總結:
異步編程雖然示例三步,可是實際上就是兩步的事情,第一步是模擬應用,跟異步編程自己沒有關係,第二步包裝一個Task返回類型的async
修飾的方法,該方法實際調用應用函數,第三步調用第二步的方法,從而執行對模擬應用的異步執行。異步
附加:
除了異步編程之外,C#還提供了併發編程相關功能,極大簡化了併發任務的開發,能夠讓開發人員無需建立線程池以及管理線程這些工做,就能夠直接使用併發開發帶來的優點。 示例代碼見Testpallral()
。async
代碼以下ide
class Program { static int i = 0; //模擬耗時的運算或者IO public static bool GetSomeThing(string a) { Thread.Sleep((new Random()).Next()%10*1000); i++; Console.WriteLine(DateTime.Now.ToLongTimeString()+"5-" + Thread.GetCurrentProcessorId().ToString()); return true; } //生成一個task類型,其中包裝調用GetSomeThing public static Task<bool> GetSomeThingAsync(string a) { return Task.Run<bool>(()=> { return GetSomeThing(a); } ); }
//方式1:包裝給調用方使用的方法,使用async修飾,由於裏面有await。 調用方執行到await會當即返回,後續的內容再也不直接調用, await以後的方法都會在可能在其餘線程中使用, public async static void ConsumeManyTime() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "3-" +Thread.GetCurrentProcessorId().ToString()); bool result = await GetSomeThingAsync("test"); Console.WriteLine(DateTime.Now.ToLongTimeString() + "4-" +Thread.GetCurrentProcessorId().ToString()); } //方式2:這種調用方式是在異步執行完畢後,能夠繼續執行預約的後續函數,能夠理解爲一種回調機制。 public static void ContinueTaskWithConsumeManyTime() { Task<bool> t1 = GetSomeThingAsync("test"); t1.ContinueWith(t => { Console.WriteLine("after await finished " + t.Result + " " + Thread.GetCurrentProcessorId().ToString() + " " + i.ToString()); }); } //方式3:多任務等待方式 public static async void TaskWhenConsumeManyTime() { Task<bool> t1 = GetSomeThingAsync("test"); Task<bool> t2 = GetSomeThingAsync("test"); await Task.WhenAll(t1, t2); Console.WriteLine(DateTime.Now.ToLongTimeString() + "6-" + Thread.GetCurrentProcessorId().ToString()); } //async 和await的基本使用 public static void TestOne() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); ConsumeManyTime(); ConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("繼續輸入"); while (Console.ReadLine() != "stop") { Console.WriteLine("繼續輸入"); } } public static void TestWithContinue() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); ContinueTaskWithConsumeManyTime(); ContinueTaskWithConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("繼續輸入"); while (Console.ReadLine() != "stop") { Console.WriteLine("繼續輸入"); } } public static void TestWhen() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); TaskWhenConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("繼續輸入"); while (Console.ReadLine() != "stop") { Console.WriteLine("繼續輸入"); } } public static void Testpallral() { ParallelLoopResult result = Parallel.For(0, 100, async (int i) => { Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); await Task.Delay(10); Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay"); }); while (Console.ReadLine() != "stop") { Console.WriteLine("繼續輸入"); } } public static void Testpallral2() { ParallelLoopResult result = Parallel.For(0, 100,async(int i, ParallelLoopState pls) => { Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); await Task.Delay(10); if (i > 5) pls.Break(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay"); } ); while (Console.ReadLine() != "stop") { Console.WriteLine("繼續輸入"); } } static void Main(string[] args) { //TestWhen(); //Testpallral2(); } }