我是.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窗体的最有效方法是什么?
请,谢谢你。
答案 0 :(得分:3)
如果您需要执行多个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限制),您可以尝试在简单Parallel.ForEach
Task
await Task.Run(() => Parallel.ForEach(tasklist, RunTask);
// assuming RunTask is not `async Task`
答案 1 :(得分:1)
首先,您需要区分并行和异步:
当您需要使用IO异步时,通常会播放。
当您需要对计算执行某些操作时(例如归档文件) 或图像处理)是平行的东西,通常是来玩。
异步等待模式只是一个捷径,而不是银弹。
如果您只需要平行计算,我建议使用TPL中的并行工作人员,例如ParallelForEach,它们可以很好地进行优化,并且可以获得最佳性能。
如果您尝试执行某些IO操作,这可能是有意义的,但或多或少处理大量处理数据 - 如服务器应用程序。
您的处理器无法执行更多操作
如果您的任务不平行,任何平行的工作人员都无法帮助您。 请注意任何上下文切换都有一些成本。 TaskSheduler将使用队列来减少线程数,但它会再做一些工作。
线程新线程是邪恶的(至少在这里)。您的处理器将更频繁地切换到另一个线程(更多线程 - 更多交换机)
<强>最后:强> 当你不知道事情是如何运作时,尽量不要使用TPL的东西。只需使用您需要的类,不要进行真正优化的优化。
<强> PS 强> 在UI中使用ContinueWith。 TPT中的任何内容都将返回具有此方法的任务, 更新UI确保您当前所在的主题。