本文介绍: 例如,如果要使用并行循环来计算随后应在 UI 控件中呈现的某些数据,则应考虑在任务实例内执行循环,而不是直接在 UI 事件处理程序中执行。如果尝试从在 UI 线程上执行的并行循环内更新 UI 控件,将可能会导致状态损坏、异常、更新延迟甚至死锁,具体将取决于 UI 更新的调用方式。在下面的示例中,在所有的迭代完成之前,并行循环将阻止它在其上执行的 UI 线程。在嵌套的循环中,最有可能发生过度并行化的情况。在某些情况下,任务并行库将对任务进行内联操作,这意味着它将在当前正在执行的线程上的任务上运行。
本文内容
在许多情况下,与普通的顺序循环相比,Parallel.For 和 Parallel.ForEach 可以显著提升性能。 但是,对循环进行并行化的工作增加了复杂性,可能会导致在顺序代码中出现不常见或根本不会遇到的问题。 本主题列出了一些在编写并行循环时要避免的做法。
1、不要假定并行的速度始终更快
在某些情况下,并行循环可能比它等效的顺序循环的运行速度更慢。 基本的经验法则是具有较少迭代和快速用户委托的并行循环未必会快很多。 但是,由于性能会涉及到很多因素,因此我们建议始终衡量实际的结果。
2、避免写入共享内存位置
在顺序代码中,从静态变量或类字段中读取或写入静态变量或类字段的情况很常见。 但是,每当多个线程同时访问此类变量时,则很有可能会出现争用条件。 即使可以使用锁来同步对变量的访问,但同步开销可能会对性能造成损害。 因此,我们建议尽可能地避免在一个并行循环中访问共享状态,或至少限制对共享状态的访问。 为此,最好使用 Parallel.For 和 Parallel.ForEach 的重载,以便在循环执行期间使用 System.Threading.ThreadLocal<T> 变量存储线程本地状态。
3、避免过度并行化
通过使用并行循环,将会产生对源集合进行分区和同步工作线程的开销成本。 计算机上的处理器数量进一步限制了并行化的优点。 仅在一个处理器上运行多个受计算限制的线程时,速度并不会得到提升。 因此,必须要小心,不要对循环进行过度并行化。
在嵌套的循环中,最有可能发生过度并行化的情况。 在大多数情况下,除非满足以下一个或多个条件,否则最好仅对外部循环进行并行化:
4、避免调用非线程安全方法
5、限制调用线程安全方法
6、注意线程关联问题
7、在由 Parallel.Invoke 调用的委托中等待时请谨慎使用
8、不要假定 ForEach、For 和 ForAll 的迭代始终并行执行
9、避免在 UI 线程上执行并行循环
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。