2013-07-09 134 views
4

我在執行異步延遲任務時遇到了一些麻煩。我正在編寫一個需要以數十/數十萬個異步執行腳本的比例運行的應用程序。我正在使用C#Actions來執行此操作,有時在執行特定序列的過程中,爲了使腳本正確執行,需要等待外部資源達到預期狀態。起初,我使用Thread.Sleep()寫了這個,但結果是應用程序性能中的魚雷,所以我正在尋找async/await進行異步睡眠。但我無法讓它實際等待暫停!有人可以解釋這個嗎?C#異步等待Task.delay中的操作

static void Main(string[] args) 
    { 
     var sync = new List<Action>(); 
     var async = new List<Action>(); 

     var syncStopWatch = new Stopwatch(); 
     sync.Add(syncStopWatch.Start); 
     sync.Add(() => Thread.Sleep(1000)); 
     sync.Add(syncStopWatch.Stop); 
     sync.Add(() => Console.Write("Sync:\t" + syncStopWatch.ElapsedMilliseconds + "\n")); 

     var asyncStopWatch = new Stopwatch(); 
     sync.Add(asyncStopWatch.Start); 
     sync.Add(async() => await Task.Delay(1000)); 
     sync.Add(asyncStopWatch.Stop); 
     sync.Add(() => Console.Write("Async:\t" + asyncStopWatch.ElapsedMilliseconds + "\n")); 

     foreach (Action a in sync) 
     { 
      a.Invoke(); 
     } 

     foreach (Action a in async) 
     { 
      a.Invoke(); 
     } 
    } 

執行的結果是:

同步:999

異步:2

我如何得到它異步等待?

回答

7

您遇到了async void的問題。當您將async lambda傳遞給Action時,編譯器正在爲您創建一個async void方法。

作爲一種最佳實踐,您應該避免async void

要做到這一點的一種方法是讓您的動作列表實際上是List<Func<Task>>而不是List<Action>。這允許您排隊async Task方法而不是async void方法。

這意味着您的「執行」代碼將不得不等待每個Task完成。此外,你的同步方法將不得不返回Task.FromResult(0)或類似的東西,所以他們匹配Func<Task>簽名。

如果您想要更大範圍的解決方案,我建議您強烈考慮TPL數據流,而不是創建自己的隊列。