1.非同步同步的定義 同步方法:多個任務一個一個執行,同一時刻系統中只有一個任務在執行 非同步方法:發起一個調用,並不等著計算結束,而是直接去運行下一行;剛纔的計算,會啟動一個新的線程去執行 2.非同步同步的比較 2.1. 同步方法卡界面,因為UI線程忙於計算;非同步多線程方法不卡界面,主線程閑置,計算任務 ...
1.非同步同步的定義
同步方法:多個任務一個一個執行,同一時刻系統中只有一個任務在執行
非同步方法:發起一個調用,並不等著計算結束,而是直接去運行下一行;剛纔的計算,會啟動一個新的線程去執行
2.非同步同步的比較
2.1. 同步方法卡界面,因為UI線程忙於計算;非同步多線程方法不卡界面,主線程閑置,計算任務交給子線程在做;
2.2. 同步方法慢,只有一個線程計算;非同步多線程方法快,多個線程併發計算;
多線程的資源消耗更多,線程並不是越多越好(資源有限/管理線程也消耗資源)
2.3. 非同步多線程是無序的:啟動無序 執行時間不確定 結束無序,,
所以不要試圖通過啟動順序或者時間等待來控制流程
3.非同步如何控制執行順序
3.1.回調
//IasyncResult,可用於監視調用進度
//DoSomethingLong方法名稱(要執行的操作)
Action<string> act = this.DoSomethingLong;
IAsyncResult iAsyncResult = null;
AsyncCallback callback = ar =>
{
// Console.WriteLine(object.ReferenceEquals(ar, iAsyncResult));
Console.WriteLine(ar.AsyncState);
Console.WriteLine($"這裡是BeginInvoke調用完成之後才執行的。。。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
};
iAsyncResult = act.BeginInvoke("btnAsync_Click", callback, "非同步學習");
3.2.等待
//IAsyncResult.IsCompeted確定非同步調用何時完成(輪詢)
Action<string> act = this.DoSomethingLong;
IAsyncResult iAsyncResult = act.BeginInvoke("btnAsync_Click", null, null);
int i = 1;
while (!iAsyncResult.IsCompleted)//1 卡界面,主線程在等待 2 邊等待邊做事兒 3有誤差(時間)
{
if (i < 10)
{
Console.WriteLine($"文件上傳{i++ * 10}%。。。請等待");
}
else
{
Console.WriteLine("已完成99%。。。馬上結束");
}
Thread.Sleep(200);//誤差時間
}
Console.WriteLine("文件上傳成功!!!");
3.3.狀態
//使用 IAsyncResult.AsyncWaitHandle 獲取 WaitHandle,使用它的 WaitOne 方法將執行一直阻塞到發出 //WaitHandle 信號,然後調用
Action<string> act = this.DoSomethingLong;
IAsyncResult iAsyncResult = act.BeginInvoke("btnAsync_Click", null, null);
//非同步變同步(狀態)
iAsyncResult.AsyncWaitHandle.WaitOne();//一直等待任務完成,第一時間進入下一行
iAsyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任務完成,第一時間進入下一行
//最多等待1000ms,超時控制
iAsyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,否則就進入下一行,可以做一些超時控制
//調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果非同步調用未完成,EndInvoke 將一直阻塞到
//非同步調用完成。
act.EndInvoke(iAsyncResult);//等待
4.其他相關知識
任何的非同步多線程,都是跟委托相關。委托中的Invoke方法 是同步的。BeginInvoke開始一個非同步的請求,調用線程池中一個線程來執行。
4.1.非同步獲取返回值
Func<int, string> func = i => i.ToString();
IAsyncResult iAsyncResult = func.BeginInvoke(DateTime.Now.Year, ar =>
{
string resultIn = func.EndInvoke(ar);//對於每個非同步操作,只能調用一次 EndInvoke。
Console.WriteLine($"This is {ar.AsyncState} 的非同步調用結果 {resultIn}");
}, "非同步參數");
//string result = func.EndInvoke(iAsyncResult);//獲取返回值