C 非同步程式設計基礎(七)非同步原理

2022-06-19 19:15:19 字數 3816 閱讀 3373

參考資料:

c# 非同步程式設計基礎(一)執行緒和阻塞

c# 非同步程式設計基礎(二)執行緒安全、向執行緒傳遞資料和異常處理

c# 非同步程式設計基礎(三)執行緒優先順序、訊號和執行緒池

c# 非同步程式設計基礎(四) 富客戶端應用程式的執行緒 和 同步上下文 synchronization contexts

c# 非同步程式設計基礎(五)task

c# 非同步程式設計基礎(六)continuation 繼續/延續 、taskcompletionsource、實現 task.delay

c# 非同步程式設計基礎(七)非同步原理

c# 非同步程式設計基礎(八) 非同步函式

c# 非同步程式設計基礎(九) 非同步中的同步上下文、valuetask

c# 非同步程式設計基礎(十) 取消(cancellation)、進度報告、tap(task-based asynchronous pattern)、task組合器

同步操作會在返**用者之前完成它的工作

非同步操作會在返**用者之後去做它的(大部分)工作

非同步發方法更為少見,會啟用併發,因為它的工作會與呼叫者並行執行

非同步的方法通常很快(立即)就返回到呼叫者,所以叫非阻塞方法

目前見到的大部分的非同步方法都是通用目的的:

thread.start

task.run

可以將continuation附加到task的方法

...非同步程式設計的原則是將長時間執行的函式寫成非同步的

傳統的做法是將長時間執行的函式寫出同步的,然後從新的執行緒或task進行呼叫,從而按需引入併發

上述非同步方式的不同之處在於,它是從長時間執行函式的內部啟動併發。這有兩點好處:

io-bound併發可不使用執行緒來實現(用**)。可提高可擴充套件和執行效率

富客戶端在worker執行緒會使用更少的**,簡化了執行緒安全性

編寫高效處理大量併發io的應用程式(典型的:服務端應用)

挑戰的並不是執行緒安全(因為共享狀態通常是最小化的),而是執行效率

特別的,每個網路請求並不會消耗乙個執行緒

在富客戶端應用裡簡化執行緒安全

如果call graph(呼叫圖)中任何乙個操作是長時間執行的,那麼整個call graph必須執行在worker執行緒上,以保證ui響應

得到乙個橫跨多個方法的單一併發操作(粗粒度)

需要為call graph中的每個方法考慮執行緒安全

非同步的call graph,直到需要的時候才開啟乙個執行緒,通常較淺(io-bound操作完全不需要)

其它的方法可以在ui執行緒執行,執行緒安全簡化

併發的粒度適中

一連串小的併發操作,操作之間會彈回到ui執行緒

為了獲得上述好處,下列操作建議非同步編寫:

io-bound和complute-bound操作

執行超過50毫秒的操作

另一方面過細的粒度會損害效能,因為非同步操作也有開銷

task非常適合非同步程式設計,因為它們支援continuation(它對非同步非常重要)

第十六講裡面taskcompletionsource的例子

taskcompletionsource是實現底層io-bound非同步方法的一種標準方式

對於compute-bound方法,task.run會初始化繫結執行緒的併發

把task返**用者,建立非同步方法

非同步程式設計的區別:目標是在呼叫圖的較低位置來這樣做

富客戶端應用中,高階方法可以保留在ui執行緒和訪問控制以及共享狀態上,不會出現執行緒安全問題

同步版

static void main(string args)

//相當於ui執行緒

static void displayprimecounts()

console.writeline("done!");

}static int getprimescount(int start, int count)

結果

非同步版,但是輸出不是我們想要的結果

static void main(string args)

//相當於ui執行緒

static void displayprimecounts()

console.writeline("done!");

}static taskgetprimescountasync(int start, int count)

結果

上述例子

需要對task的執行序列化

例如task b依賴於task a的執行結果

上述例子為此,必須在continuation內部觸發下一次迴圈

同步版

static void main(string args)

static void displayprimecounts()

static void displayprimecountsfrom(int i)

else

});}static taskgetprimescountasync(int start, int count)

結果

非同步版,利用狀態機,太麻煩

class program

static task displayprimecountsasync()

public static taskgetprimescountasync(int start, int count)

}class primesstatemachine

}public void displayprimecountsfrom(int i)

else

});}

}

結果

3、async和await

對於不想複雜的實現非同步非常重要

原理:狀態機

非同步程式設計時,非同步函式被編譯為包含狀態機的形式,使得**在某處停留,等待某個任務完成

修改後的例子

static async task main(string args)

async static task displayprimecountsasync()

console.writeline("done");

}//凡是返回task的方法都可以用await進行呼叫

static taskgetprimescountasync(int start, int count)

結果

非同步程式設計基礎

本質上適合非同步的操作有 http請求,資料庫指令,web服務呼叫等。1 暫停一段時間 以非同步方式 以非同步的方式暫停一段時間,這在進行單元測試或者重試延遲時非常有用。task類有乙個返回task物件的靜態函式delay,下面是其中的乙個 public static task delay time...

非同步程式設計(基礎)

1.非同步程式設計並不是多執行緒 2.非同步程式設計只是在io操作 cpu操作 將主線程切換出去執行其他操作,不阻塞主線程,從而提公升系統併發效能 3.非同步並不能提公升程式本身執行速度,只是能在同一時間點處理更多的任務。舉個燒水的例子 如圖 上圖說明。從開始燒水到水開 不管同步還是非同步,時間是相...

C 非同步程式設計

同步方法和非同步方法的區別 同步方法呼叫在程式繼續執行之前需要等待同步方法執行完畢返回結果 非同步方法則在被呼叫之後立即返回以便程式在被呼叫方法完成其任務的同時執行其它操作 非同步程式設計概覽 net framework 允許您非同步呼叫任何方法。定義與您需要呼叫的方法具有相同簽名的委託 公共語言執...