繁体   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