微軟宣佈Visual Studio Async CTP今日(2010年10月28日),介紹了async
和await
關鍵字爲異步方法執行C#/ VB。C#異步 - 它是如何工作的?
首先,我認爲編譯器將關鍵字轉換爲創建線程,但根據white paper和Anders Hejlsberg的PDC presentation(在31:00),異步操作完全在主線程上發生。
我怎麼能有一個操作相同的並行線程上執行?它在技術上如何可能以及在IL中實際翻譯的功能是什麼?
微軟宣佈Visual Studio Async CTP今日(2010年10月28日),介紹了async
和await
關鍵字爲異步方法執行C#/ VB。C#異步 - 它是如何工作的?
首先,我認爲編譯器將關鍵字轉換爲創建線程,但根據white paper和Anders Hejlsberg的PDC presentation(在31:00),異步操作完全在主線程上發生。
我怎麼能有一個操作相同的並行線程上執行?它在技術上如何可能以及在IL中實際翻譯的功能是什麼?
它的工作原理類似於yield return
關鍵字在C#2.0。
異步方法實際上並不是普通的順序方法。它被編譯成狀態機(一個對象),並有一些狀態(局部變量被轉換成對象的字段)。在兩個使用await
之間的每個代碼塊是狀態機的一個「步驟」。
這意味着,當方法啓動時,它只是運行第一步,然後狀態機返回並安排一些工作要完成 - 工作完成後,它將運行狀態機的下一步。例如下面的代碼:
async Task Demo() {
var v1 = foo();
var v2 = await bar();
more(v1, v2);
}
將被轉換爲類似:
class _Demo {
int _v1, _v2;
int _state = 0;
Task<int> _await1;
public void Step() {
switch(this._state) {
case 0:
this._v1 = foo();
this._await1 = bar();
// When the async operation completes, it will call this method
this._state = 1;
op.SetContinuation(Step);
case 1:
this._v2 = this._await1.Result; // Get the result of the operation
more(this._v1, this._v2);
}
}
最重要的部分是,它只是使用了SetContinuation
方法來指定操作完成時,它應該叫Step
方法(並且該方法知道它應該使用_state
字段運行原始代碼的第二位)。你可以很容易想象,SetContinuation
就像btn.Click += Step
,它可以完全在一個線程上運行。
C#中的異步編程模型非常接近F#異步工作流程(事實上,除了一些技術細節外,它本質上是一回事),使用async
編寫反應性單線程GUI應用程序是一個相當有趣的領域 - 至少我認爲是這樣 - 例如this article(也許我現在應該寫一個C#版本:-))。
該翻譯類似於迭代器(和yield return
),事實上,有可能使用迭代器在C#中實現異步編程。前一段我寫了an article about that - 我認爲它仍然可以讓你對翻譯的工作方式有所瞭解。
據我瞭解,有什麼async
和await
關鍵字做的是,每一個async
方法採用await
關鍵字時,編譯器將會把該方法的其餘部分將在完成異步操作時所計劃的延續。這允許async
方法立即返回給調用者,並在異步部分完成時恢復工作。
根據現有的文件也有很多細節,但除非我錯了,這是它的要點。
當我看到它的異步方法的目的不是爲了運行大量的並行代碼,但砍異步方法分成若干小塊的,可以根據需要調用。關鍵在於編譯器將使用任務/連續處理所有複雜的回調連線。這不僅降低了複雜度,而且允許像傳統同步代碼那樣或多或少寫入異步方法。
如何在同一個線程上並行執行一個操作?
你不行。 異步不是「並行性」或「併發性」。異步可能是用並行來實現的,或者它可能不是。它可以通過將工作分解成小塊,將每個工作塊放到一個隊列中,然後在線程碰巧沒有做其他事情時執行每個工作塊來實現。
我在我的博客上有一系列關於這些東西是如何工作的文章;直接與這個問題密切相關的人可能會在下週的星期四上升。手錶
http://blogs.msdn.com/b/ericlippert/archive/tags/async/
瞭解詳情。
它是如何安排沒有一個單獨的線程?在CLR中是否延續了一個特定的概念,允許一些輕量級的調度? – 2010-10-28 21:55:55
@ 0xA3:我相信論文說異步方法不會在它自己的線程上運行。即就像TPL一樣,根據具體情況,它將是當前線程和線程池線程的混合。 – 2010-10-28 22:00:30