異步學習代碼筆記
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp7
{
class Program
{
[STAThread]
static void Main(string[] args)//三個方法如果同步執行需要16s,而採用異步方式不僅主線程不會被阻塞,執行完也只需要10s,因爲他們是並行執行的
{
Console.WriteLine("Main_" + Thread.CurrentThread.ManagedThreadId);
Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready_"+DateTime.Now);
Task<Egg> eggs = FryEggs(2);//1s
Console.WriteLine("eggs are ready_"+DateTime.Now);
Task<Bacon> bacon = FryBacon(3);//5s
Console.WriteLine("bacon is ready_" + DateTime.Now);
Task<Toast> toast = ToastBreadAsync1(2);//10s
Toast result1 = toast.Result;
Bacon result2 = bacon.Result;
Egg resul3 = eggs.Result;
Console.WriteLine("toast is ready_" + DateTime.Now);
Juice oj = PourOJ();
Console.WriteLine("oj is ready");
Console.WriteLine("Breakfast is ready!");
Console.ReadLine();
}
private static Juice PourOJ()
{
return new Juice();
}
private async static Task<Toast> ToastBreadAsync1(int v)//需要依賴返回值進行進一步的處理則需要封裝成async異步方法,以便await結果進行後續處理
{
Toast toast = await ToastBread(v);
ApplyButter(toast);//相當於回調的代碼
ApplyJam(toast);//相當於回調的代碼
return toast;
}
private static Task<Toast> ToastBread(int v)//供ToastBreadAsync1封裝成異步方法
{
return Task<Toast>.Factory.StartNew(()=> { Thread.Sleep(1000); Console.WriteLine("Toast_" + Thread.CurrentThread.ManagedThreadId); return new Toast(); });
}
private static Task<Bacon> FryBacon(int v)//如果無需關心返回值則調用方直接調用任務方法而無需封裝成async異步方法
{
return Task<Bacon>.Factory.StartNew(() => { Thread.Sleep(5000); Console.WriteLine("Bacon_"+Thread.CurrentThread.ManagedThreadId); return new Bacon(); });
}
private static Task<Egg> FryEggs(int v)//如果無需關心返回值則調用方直接調用任務方法而無需封裝成async異步方法
{
return Task<Egg>.Factory.StartNew(() => { Thread.Sleep(10000);Console.WriteLine("Eggs_"+Thread.CurrentThread.ManagedThreadId); return new Egg(); });
}
private static void ApplyJam(Toast toast)//類似回調的方法
{
Thread.Sleep(3000);
Console.WriteLine("ApplyJam finished_" + DateTime.Now);
}
private static void ApplyButter(Toast toast)//類似回調的方法
{
Thread.Sleep(3000);
Console.WriteLine("ApplyButter finished_" + DateTime.Now);
}
private static Coffee PourCoffee()
{
Console.WriteLine("Start PourCoffee");
return new Coffee();
}
}
internal class Toast
{
}
internal class Coffee
{
}
//要點1:創建Task除了可以用new+手動start,還可以通過Task<Egg>.Factory.StartNew()實現;
//要點2:如上帶有返回值的異步方法ToastBreadAsync1的返回值與return的值類型是不一樣的。
//且其返回的Task<Toast>爲其包含內部兩個同步方法ApplyButter/ApplyJam的Task<Toast>,
//而不單純是 await ToastBread(v)返回的Task
//要點3:當調用異步方法的Task.Result時會阻塞線程。調用Task.wait()顯式阻塞線程.
//在web開發中假設需要調用多個接口獲取返回值合併輸出到web頁面時的場景會用到線程阻塞。
}