同步方法api
1 Console.WriteLine($"****************Sync Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 Action<string> action = this.DoSomething; 3 for (int i = 0; i < 5; i++) 4 { 5 string name = string.Format($"Sync_{i}"); 6 action.Invoke(name); //等價 方法直接執行 this.DoSomething(name); 7 } 8 Console.WriteLine($"****************Sync End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
異步方法多線程
1 Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 for (int i = 0; i < 5; i++) 3 { 4 var name = $"Async_{i}"; 5 action.BeginInvoke(name,null,null); 6 } 7 Console.WriteLine($"****************Async End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
1 /// <summary> 2 /// 一個比較耗時耗資源的私有方法 3 /// </summary> 4 private void DoSomething(string name) 5 { 6 Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 7 long lResult = 0; 8 for (int i = 0; i < 1_000_000; i++) 9 { 10 lResult += i; 11 } 12 Thread.Sleep(2000); 13 Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 14 }
運行上面的代碼,咱們發現幾個問題:併發
一、同步方法卡界面:主線程(UI線程)忙於計算,無暇他顧 ;異步多線程方法不卡界面:主線程閒置,計算任務交給子線程完成異步
二、同步方法慢,只有一個線程計算;async
異步多線程方法快,由於5個線程併發計算 差很少5倍,也不到5倍,CPU密集型計算(資源受限)ide
多線程實際上是資源換性能,1 資源不是無限的 2 資源調度損耗性能
三、同步方法有序進行;this
異步多線程無序spa
啓動無序:線程資源是向操做系統申請的,由操做系統的調度策略決定,因此啓動順序隨機操作系統
執行時間無序:同一個任務同一個線程,執行時間也不肯定,CPU分片
結束無序:以上相加,結束也無序
AsyncCallback 異步回調:將後續動做經過回調參數傳遞進去,子線程完成計算後,去調用這個回調委託
AsyncState 用戶定義對象:能夠做爲回調的參數
1 Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 AsyncCallback callback = ar => Console.WriteLine($"{nameof(AsyncCallback)} 是否完成:{ar.IsCompleted} 用戶定義對象:{ar.AsyncState} {Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 3 for (int i = 0; i < 5; i++) 4 { 5 var name = $"Async_{i}"; 6 action.BeginInvoke(name, callback, i); 7 } 8 Console.WriteLine($"****************Async End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
IAsyncResult 對異步調用操做的描述
IsCompleted 斷定異步任務是否完成
while (!asyncResult.IsCompleted) //if(!asyncResult.IsCompleted)
{
// Do SomeThing
}
WaitOne 等待,即時等待 限時等待
asyncResult.AsyncWaitHandle.WaitOne();//直接等待任務完成
asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任務完成
asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超時就不等了
EndInvoke 即時等待,並且能夠獲取委託的返回值 一個異步操做只能End一次
1 Func<int, int> func = Sum; 2 func.BeginInvoke(10, ar => { 3 Console.WriteLine($"線程ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")} 計算結果:{func.EndInvoke(ar)}"); 4 }, null); 5 6 7 IAsyncResult asyncResult = func.BeginInvoke(5,ar => 8 { 9 //int iEndResultIn = func.EndInvoke(ar); 10 }, null); 11 int iEndResult = func.EndInvoke(asyncResult);
EndInvoke 能夠寫在BeginInvoke裏也能夠寫在外面 但只能寫一次 不然會報錯
微軟文檔:
IAsyncResult:https://docs.microsoft.com/zh-cn/dotnet/api/system.iasyncresult?view=netframework-4.8
AsyncCallback:https://docs.microsoft.com/zh-cn/dotnet/api/system.asynccallback?view=netframework-4.8