2017-04-06 150 views
8

我们有一个我们正在支持的旧项目,并且最有可能由于多线程而发生的问题。 原执行者在执行问题部分之前通过执行Thread.sleep'固定'它。 解决方法可行,但由于该部分位于循环内,因此thread.sleep会在该部分完成所需的时间内添加多个分钟。有没有办法强制应用程序作为单线程运行?

在过去的一个月中,我们一直在尝试用较低的睡眠值,但我们希望找到根本原因。在我们的调查中,我们对私人物品做了lock,只要我们觉得这样会有所帮助。 我们寻找任何可能产生额外线程的东西 - 无法找到。 没有Thread.start并且没有ThreadPool用法。 令我们困惑的是,在调试过程中,我们发现我们的主线程在大约8个其他线程中,我们不知道是谁产生了它们。 这些是后台线程,所以首先想到的是线程池,但正如我提到的代码中没有提到它。

它是.net 2.0所以没有Async s。 这只是大型应用程序的一部分,所以它是一个Windows服务,但我们将其作为CMD运行,以便能够轻松进行调试主应用程序本身是一个Windows窗体桌面应用程序。 它也使用COM +组件,如果有任何帮助。

我试过[STA]而不是[MTA]。 也如上所述锁定。 MemoryBarrier也是如此。

我们仍然遇到问题。

该问题基本上是损坏的数据集和对象的空值,他们不应该。 它发生在每25-100次迭代大约一次,因此再生不是直接进行的,但我们专门为此问题设计了一个测试来尝试再现它。

所有这些都将我们引向线程问题的方向。

回到最初的问题 - 谁可能通过产生这些额外的线程,我们如何防止这些线程被创建?

enter image description here

请注意标有红色的线 - 这些都是后台线程而据我们可以看到没有提到他们的代码。

截图中的可疑线程正在主动修改dataset中的列。问题是 - 调用线程执行的SetColValueOnRow函数的方法是典型的,并且不使用任何类型的线程。

此应用程序的CPU关联设置为1个核心[原工作周围的部分]

感谢

编辑:数据库是Oracle 12c的,但写之前,我们面对发生的问题数据库。 他们通常在数据集,其中整个记录或它的一些列的可擦一次每隔几个测试迭代

+0

什么类型的应用程序(winforms,service,...) – pm100

+0

这只是更大的应用程序的一部分,所以它是一个Windows服务,但我们将其作为CMD运行,以便能够轻松进行调试 主应用程序本身是一个Windows窗体桌面应用程序。 – AngelicCore

+0

当再现/调试这个问题时,我们只运行这个部分,我们不运行应用程序的其余部分。 – AngelicCore

回答

2

我认为你需要调查原因的Thread.sleep工作发生。这听起来不像代码本身产生额外的线程,但你必须通过整个代码库才能找到它 - 包括COM +组件。

所以我要做的第一件事就是在调试中启动程序,只需按F10键即可进入程序。然后打开线程调试窗口,看看你是否看到与你的问题中给出的相同数量的线程。如果你这样做,那么这些只是线程池中的线程,你的问题可能与多线程无关。

如果看不到相同数量的线程,则尝试在程序的各个阶段设置断点,并查看是否可以找到在哪些线程创建的位置。当你找到他们创建的地方时,你可以尝试在那个地方添加一些锁定。但是,您的问题仍然可能不是由多个线程损坏内存引起的。您应该调查,直到您确信问题是由于多个线程或其他问题。

我怀疑问题可能与一个或多个COM +组件有关,也可能是代码正在调用一些长时间运行的数据库存储过程。无论如何,我怀疑Thread.sleep的工作原因是因为在开始下一个操作之前,它给了可疑组件足够的时间来完成它的操作。

如果这个理论是正确的,那么它表明在操作和Thread.Sleep被赋予足够大的值以允许操作完成时存在一些交互 - 没有交互问题。这也表明,也许其中一个COM +组件正在异步地做一些事情。解决方案可能是使用COM +组件代码中的锁或关键部分。另一个想法是重新设计导致问题的代码段,以允许同时进行多个操作。

因此,您遇到的问题可能不是由于您正在查看的C#代码中存在多个线程 - 可能是由于长时间运行的操作,如果在启动之前没有足够的时间来完成,有时会失败下一个操作。这可能是也可能不是由于C#代码中的多个线程。

+0

你是对的 - 这是我想要做的事情之一。该应用程序是巨大的,并不简明,所以显然这将需要很长的时间。 – AngelicCore

相关问题