[英]How to Await Task.Run(action) when action is unknown
我有以下代碼:
static void Main(string[] args)
{
Run(() => LongProcess()).ContinueWith( t => Run(() => LongerProcess()));
int count = 5;
do
{
Console.WriteLine(count.ToString());
Thread.Sleep(100);
count++;
} while (count < 20);
Console.ReadKey();
}
private static void LongProcess()
{
Console.WriteLine("Long Process 1");
Thread.Sleep(2000);
Console.WriteLine("Long Process 2");
}
private static void LongerProcess()
{
Console.WriteLine("Longer Process 1");
Thread.Sleep(3000);
Console.WriteLine("Longer Process 2");
}
private static async Task Run(Action action)
{
await Task.Run(action); //shouldn't this wait until the action is completed??
// how should I modify the code so that the program waits until action is done before returning?
}
使用await Task.Run(action);
,我期待該程序將等到任何action
完成,然后再進行下一步。 換句話說,我期待輸出如下:
Long Process 1
Long Process 2
Longer Process 1
Longer Process 2
5
6
7
8
...
19
但是,輸出就像
Long Process 1
5
6
7
8
...
19
Long Process 2
Longer Process 1
Longer Process 2
問題:
await Task.Run
等待action
完成?使用await
不等待,這就是重點。 如果您想等待,請使用Task.Wait
。
但是, async
方法的執行只會在等待的任務完成后(它是一個延續)才會恢復。 讓我們看看你的async
方法:
private static async Task Run(Action action)
{
await Task.Run(action);
// There is nothing here
}
任務完成后沒有代碼要執行……好吧, async
方法返回一個完成時完成的任務。 讓我們看看你是否在await
……
Run(() => LongProcess()).ContinueWith( t => Run(() => LongerProcess()));
你沒有。 您啟動該任務並忘記它。
我認為這就是你想要的:
static async void Main(string[] args)
{
await Run(() => LongProcess());
await Run(() => LongerProcess());
int count = 5;
do
{
Console.WriteLine(count.ToString());
Thread.Sleep(100);
count++;
} while (count < 20);
Console.ReadKey();
}
注意:Async Main 是 C# 7.1 的一項功能。
此代碼將運行調用LongProcess
的任務,然后作為延續運行LongerProcess
的任務,然后作為延續代碼的其余部分。
為什么你想要它而不是同步調用這些方法是我無法理解的。
順便說一下,在async
方法中,您可以使用await Task.Delay(milliseconds)
而不是Thread.Sleep(milliseconds)
。 優點是線程不等待。 這就像在單個執行計時器上進行延續。
如果async/await
只是延續,您可能想知道為什么人們想要使用它們而不是ContinueWith
。
讓我給你幾個理由:
async/await
代碼更容易閱讀。 減少了使代碼蒙上陰影的嵌套內容。 您可以獨立於理解線程來理解代碼的作用。async/await
代碼更容易編寫。 你只是把它寫成好像它都是同步的,有一些async
和await
在那里閃閃發光。 您可以編寫同步代碼,然后擔心如何使其並發。 您最終也會寫得更少,這意味着您的工作效率更高。async/await
代碼更智能™。 編譯器將您的代碼重寫為連續狀態機,允許您將await
放入語句中,而無需任何代碼體操™。 這擴展到異常處理。 你看,在你的即發即棄的任務繼續中,你沒有處理異常。 如果LongerProcess
拋出怎么辦? 好吧,使用async/await
您可以將await
放在try ... catch
,它會做正確的事情™。這都是很好的關注點分離。
您可能還想知道在什么情況下使用async/await
代替同步代碼是個好主意。 答案是它在處理 I/O 操作時大放異彩。 在與外部系統交互時,通常不會立即得到響應。 例如,如果要從磁盤讀取或從網絡下載。
事實上,如果您認為操作表單和處理其事件是 I/O 綁定操作(因為它們是)。 你會發現它們是使用async/await
的好地方。 特別是考慮到 UI 線程的同步上下文默認情況下將在同一線程上保持延續。 當然,您可以使用Task.Run
將async/await
與 CPU 綁定操作一起使用。 什么時候是個好主意? 啊,是的,當您想保持 UI 響應時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.