我们有一个我们正在支持的旧项目,并且最有可能由于多线程而出现问题。
最初的实施者'固定'在执行有问题的部分之前执行Thread.sleep
。
解决方法有效,但由于该部分位于循环内,thread.sleep
会将该部分完成所需的时间增加多分钟。
在过去的一个月里,我们一直在试验较低的睡眠值,但我们希望找到根本原因。在我们的调查过程中,我们对私人物品进行了lock
,无论我们觉得哪有帮助。
我们寻找任何可能产生额外线程的东西 - 没有找到。
没有Thread.start和ThreadPool用法。
令我们困惑的是,在调试过程中,我们发现我们的主要线程在大约8个其他线程的中间,我们不知道是谁产生了它们。
这些是后台线程,所以我首先想到的是线程池,但我在代码中没有提到它。
是.net 2.0所以没有Async
s。
这只是更大的应用程序的一部分,所以它是一个Windows服务,但我们将其作为CMD运行,以便能够轻松调试它主要的应用程序本身是一个Windows窗体桌面应用程序。
如果有任何帮助,它还使用COM +组件。
我已尝试[STA]
而不是[MTA]
。
同样按上述方式锁定。
MemoryBarrier
也是。
我们仍然遇到了这个问题。
问题基本上是损坏的数据集和它们不应该存在的对象中的空值。 它大概每25-100次迭代发生一次,因此复制不是直接的,但我们已经设计了一个专门针对这个问题的测试,试图重现它。
所有这些都指向了线程问题的方向。
回到原来的问题 - 谁可能通过产生这些额外的线程,我们如何防止这些线程被创建?
请注意标有红色的线程 - 这些是后台线程,据我们所知,代码中没有提及它们。
屏幕截图中的可疑线程正在主动修改dataset
中的cols。问题是 - 调用线程正在执行的SetColValueOnRow
函数的方法很典型,并且不使用任何类型的线程。
此应用程序的CPU亲和力设置为1 Core [原始解决方案的一部分]
由于
编辑:数据库是oracle 12c,但我们面临的问题是在写入数据库之前发生的。 它们通常发生在DataSet中,每隔几次测试迭代就可以擦除整个记录或一些列
答案 0 :(得分:2)
我认为您需要调查Thread.sleep的工作原理。听起来好像代码本身就产生了额外的线程,但你必须通过整个代码库才能找到它 - 包括COM +组件。
所以我要做的第一件事就是在调试中启动程序,然后按F10键进入程序。然后打开线程调试窗口,看看你是否看到问题中给出的线程数相同。如果你这样做,那么这些只是来自线程池的线程,你的问题可能与多线程无关。
如果没有看到相同数量的线程,请尝试在程序的各个阶段设置断点,看看是否可以找到创建这些线程的位置。当您找到创建它们的位置时,可以尝试在此处添加一些锁定。但是,您的问题仍然可能不是由多个线程破坏内存引起的。您应该进行调查,直到您确信问题是由多线程或其他原因造成的。
我怀疑该问题可能与一个或多个COM +组件有关,或者代码可能正在调用一些长时间运行的数据库存储过程。在任何情况下,我怀疑Thread.sleep工作的原因是因为它为可疑组件提供了足够的时间来完成其操作,然后再开始下一次操作。
如果这个理论是正确的,那么它表明操作之间存在一些交互,并且当Thread.Sleep被赋予足够大的值以允许操作完成时 - 没有交互问题。这也表明,也许其中一个COM +组件正在异步地做一些事情。解决方案可能是在COM +组件代码中使用锁或关键部分。另一个想法是重新设计导致问题同时允许多个操作的代码部分。
因此,您遇到的问题可能不是由于您正在查看的C#代码中的多个线程 - 但可能是由于长时间运行的操作,如果在启动之前没有足够的时间来完成,有时会失败下一步行动。这可能是也可能不是由于C#代码中的多个线程造成的。