[英]Wait for Parallel Programming to Finish all tasks without freezing up GUI
我是.NET中所有并行编程范例的新手,我想知道两件事:
我有一个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`
首先,您需要区分并行和异步:
当您需要使用IO进行某些操作时,通常会玩。
当您需要对计算进行某些处理(例如存档文件或图像处理)时,通常会出现并行操作。
异步等待模式只是一个快捷方式,而不是灵丹妙药。
如果您只需要并行计算,我建议使用TPL的并行人员(例如ParallelForEach),它们玩起来很酷,而且经过优化,非常好,以实现最高性能。
如果您尝试执行一些IO操作,这可能是有道理的,但处理的数据量或多或少-如服务器应用程序。
您的处理器不能做的那么多
如果您的任务不是并行的,那么任何并行人员都无法为您提供帮助。 请注意,任何上下文切换都有一定的成本。 TaskSheduler将使用队列来减少线程数,但它又做了一些工作。
线程新线程是邪恶的(至少在这里)。 您的处理器将更频繁地切换到一个线程(更多线程-更多开关)
最后:当您不知道TPL的工作原理时,请不要使用它们。 只需使用您需要的类,就不要进行没有真正优化的优化。
PS在UI中使用ContinueWith。 TPT中的任何内容都将返回具有此方法的任务,更新UI时请确保当前使用线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.