如何在.NET 中编写安全/正确的多线程代码?

2024-05-13

今天我必须修复一些使用线程的旧 VB.NET 1.0 代码。问题在于从工作线程而不是 UI 线程更新 UI 元素。我花了一些时间才发现可以使用 InvokeRequired 断言来查找问题。

除了上面提到的并发修改问题之外,还可能遇到死锁、竞争条件等问题。由于调试/修复线程问题很痛苦,我想知道如何减少该领域的编码错误/故障以及如何更轻松地找到其中的任何错误/故障。所以,我要求的是:

  • 编写多线程代码时有什么好的模式可以遵循吗?什么是该做和不该做的事情?
  • 您使用什么技术来调试线程问题?

如果适用且可能,请提供一些示例代码。答案应该与 .NET 框架(任何版本)相关。


这可能是一个massive列表 - 阅读 Joe Duffy 的优秀作品“Windows 上的并发编程 https://rads.stackoverflow.com/amzn/click/com/032143482X“了解更多细节。这几乎是一个大脑垃圾场......

  • 当您拥有锁时,尽量避免调用大量代码
  • 避免锁定类外部代码也可能锁定的引用
  • 如果您需要一次获取多个锁,请始终以相同的顺序获取这些锁
  • 在合理的情况下,使用不可变类型 - 它们可以在线程之间自由共享
  • 除了不可变类型之外,尽量避免在线程之间共享数据
  • 避免尝试使您的类型线程安全;大多数类型不需要,通常需要共享数据的代码需要控制锁定本身
  • In a WinForms app:
    • 不要在 UI 线程上执行任何长时间运行或阻塞的操作
    • 不要从 UI 线程以外的任何线程接触 UI。 (使用BackgroundWorker、Control.Invoke/BeginInvoke)
  • 尽可能避免线程局部变量(又名线程静态) - 它们可能会导致意外行为,特别是在 ASP.NET 上,其中请求可能由不同线程提供服务(搜索“线程敏捷性”和 ASP.NET)
  • 不要试图表现得聪明。无锁并发代码是hugely很难做对。
  • 记录您的类型的线程模型(和线程安全)
  • Monitor.Wait 几乎总是应该在 while 循环中与某种检查结合使用(即 while (I can't continue) Monitor.Wait(monitor))
  • 每次使用 Monitor.Pulse 和 Monitor.PulseAll 之一时,请仔细考虑它们之间的区别。
  • 插入 Thread.Sleep 来解决问题从来都不是真正的解决办法。
  • 查看“并行扩展”和“协调和并发运行时”作为使并发更简单的方法。并行扩展将成为 .NET 4.0 的一部分。

在调试方面,我没有太多建议。使用 Thread.Sleep 来增加出现竞争条件和死锁的机会是可行的,但在知道将问题放在哪里之前,您必须对问题有一个相当合理的理解。日志记录非常方便,但不要忘记代码会进入某种量子状态 - 通过日志记录观察它几乎必然会改变其行为!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在.NET 中编写安全/正确的多线程代码? 的相关文章

随机推荐