簡體   English   中英

等待並行編程完成所有任務,而不會凍結GUI

[英]Wait for Parallel Programming to Finish all tasks without freezing up GUI

我是.NET中所有並行編程范例的新手,我想知道兩件事:

  1. 我如何等待我的所有任務完成運行而又不凍結我的主要表單。
  2. 我解決以下問題的方法是否是解決此問題的最佳方法?

我有一個private async Task RunTask(string task)方法,該方法需要運行的次數與我擁有的任務數一樣多。

在一個private async void button_click(object sender, EventArgs e)類中,我有一個名為tasklist的字符串列表,該字符串列表初始化了我需要運行的任務。 我正在運行以下代碼:

Thread thread = new Thread(()=> Parallel.ForEach(tasklist, t => RunTask(t)));
thread.Start();
RunOnCompletionOfTasks();

我需要能夠利用我所有的CPU內核,並在盡可能短的時間內運行所有任務。 我認為Parallel.ForEach是實現此目標的最佳方法,但我的任務也是async因為它們的功能需要等待其他方法。 我的任務在執行期間還將一個字符串附加到類中的List<string>對象上。

Parallel.ForEach導致Windows窗體凍結,因此我將其封裝在線程中。 問題是RunOnComlpetionOfTasks(); 在我的任務完成之前運行。

什么是最有效的辦法,我跑我所有的RunTask任務,然后運行RunOnCompletionOfTasks完成后,不會凍結了Windows窗體?

謝謝,麻煩您了。

如果您需要執行多個Tasks (可以等待),那么Parallel.ForEach可能不是最佳選擇。 它是專為CPU綁定進程而設計的,不支持async操作。

您可以嘗試使用Task.WhenAll()重寫代碼:

var tasks = tasklist.Select(RunTask);
// assuming RunTask is declared as `async Task`
await Task.WhenAll(tasks);

這樣,您就可以在方法調用中利用async / await模式。

相反,如果您意識到自己的任務未正確async (並且僅與CPU綁定),則可以嘗試在一個簡單的Task執行Parallel.ForEach

await Task.Run(() => Parallel.ForEach(tasklist, RunTask);
// assuming RunTask is not `async Task`

首先,您需要區分並行和異步:

  1. 當您需要使用IO進行某些操作時,通常會玩。

  2. 當您需要對計算進行某些處理(例如存檔文件或圖像處理)時,通常會出現並行操作。

異步等待模式只是一個快捷方式,而不是靈丹妙葯。

如果您只需要並行計算,我建議使用TPL的並行人員(例如ParallelForEach),它們玩起來很酷,而且經過優化,非常好,以實現最高性能。

如果您嘗試執行一些IO操作,這可能是有道理的,但處理的數據量或多或少-如服務器應用程序。

您的處理器不能做的那么多

如果您的任務不是並行的,那么任何並行人員都無法為您提供幫助。 請注意,任何上下文切換都有一定的成本。 TaskSheduler將使用隊列來減少線程數,但它又做了一些工作。

線程新線程是邪惡的(至少在這里)。 您的處理器將更頻繁地切換到一個線程(更多線程-更多開關)

最后:當您不知道TPL的工作原理時,請不要使用它們。 只需使用您需要的類,就不要進行沒有真正優化的優化。

PS在UI中使用ContinueWith。 TPT中的任何內容都將返回具有此方法的任務,更新UI時請確保當前使用線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM