9

async關鍵字導致CIL更改(即使方法內部沒有等待),但主要是允許await存在。爲什麼我的TCS不等待?

但我沒想到的是以下情況發生:

static void Main(string[] args) 
{ 
    Task t = Go(); 
    t.Wait(); 
} 

static async Task Go() 
{ 
    Console.WriteLine(1); 
    await AAA(3000); 
    Console.WriteLine(2); 
} 


static Task<object> AAA(int a) // <--- No `async` 
{ 
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null)); 
    return tcs.Task; 
} 

本刊:

1 
(wait) 
2 

但是,如果我改變

static Task<object> AAA(int a) 

static async Task<object> AAA(int a) 

它打印:

1 
2 
(no wait) 

問題

爲什麼我看不到延遲? TCS僅在三秒後解決。同時,任務沒有解決,應該等待。

+2

我認爲[razor118](http://stackoverflow.com/a/32785865/477420)答案是問題的最佳演示 - 更改'靜態任務 AAA(int a)'到'靜態任務 AAA( int a)'(對代碼進行必要的更改)並添加'async'。 –

+0

是的,我被咬了,現在想起它 - 這是一個愚蠢的問題。每個異步方法的結果都返回一些東西 - 某個東西被一個任務包裝。所以在這裏,我實際上正在返回'任務' –

+1

愚蠢或不是你的呼叫,但肯定是教育(和寫得很好)。兩種版本的代碼(異步/非異步)看起來似乎是合理的,並且讓我感到困惑(我根據選票投注了足夠多的人)。 –

回答

8

如果沒有async關鍵字,您將返回TaskCompletionSource的任務AAA,等待它完成(這將在延遲完成後發生)。

但是,當您添加async關鍵字時,該方法返回的任務是狀態機的任務,該任務將同步完成。該任務在其中(因此)TaskCompletionSource的任務,但這不是你正在等待的任務。

如果你想這種方式來等待TaskCompletionSource的任務,你可以等待的Task<Task>內任務:

await ((Task) await AAA(3000)); 

或者等待TaskCompletionSource的並沒有返回它:

async Task AAA(int a) 
{ 
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null)); 
    await tcs.Task; 
} 

甚至更​​好,只是等待Task.Delay本身:

async Task<object> AAA(int a) 
{ 
    await Task.Delay(a); 
    return null; 
} 
6

因爲當你從一個返回類型爲Task<object>的異步方法返回Task你得到它Task<Task>與你的任務(你期待等待)裏面。那你應該怎麼做:

static async Task<object> AAA(int a) 
{ 
    await Task.Delay(a); 
    return null; 
} 

總之,儘量避免在一種方法中混合異步等待和直接任務操作。

2

由於SERG提到的,看看下面這個例子在Visual Studio:

 static async Task<int> AAA(int a) // <--- No `async` 
     { 
      TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); 
      Task.Delay(a).ContinueWith(b => 
      { 
        tcs.SetResult(1); 
      }); 
      return tcs.Task; 
     } 

你會得到錯誤是這樣的:

因爲這是一個異步方法,返回表達式的類型必須是「詮釋」的而不是'任務',因爲你的方法會同步運行。這就是爲什麼它需要返回int,而不是Task

+2

關於你的最後一個知識產權,方法*將*運行異步,它需要返回一個'int'而不是'Task ',但方法同步運行的事實isn '*爲什麼*他必須返回'int'。他需要返回一個'int',因爲所有'async'方法都將返回的值包裝在'Task'中。該方法將同步運行是真實的,但不是該錯誤的原因。 – Servy

+0

razor118,這個答案會很棒,因爲評論 - 使用一些強類型而不是「Object」會使錯誤非常明顯。或者你可以通過應用@Servy的評論來清理它。 –

+0

Serv as as know async keyword is responsible to inform compiler to build state machine。它不包含返回類型到任務。再看那 私有靜態無效測試(){} 和 私有靜態異步無效TestAsync(){} – razor118

相關問題