【发布时间】:2017-09-02 04:45:26
【问题描述】:
我们支持一个旧项目,并且很可能由于多线程而出现问题。
最初的实施者在执行有问题的部分之前通过执行Thread.sleep 来“修复”它。
解决方法有效,但由于该部分位于循环内,thread.sleep 会增加该部分完成所需的时间。
在上个月,我们一直在尝试降低睡眠值,但我们希望找到根本原因。在我们的调查期间,我们在任何我们认为有帮助的地方对私人对象进行lock。
我们寻找任何可能产生额外线程的东西 - 没有找到。
没有 Thread.start 也没有 ThreadPool 使用。
令我们困惑的是,在调试过程中,我们发现我们的主线程位于大约 8 个其他线程的中间,我们不知道这些线程是谁产生的。
这些是后台线程,所以我首先想到的是线程池,但正如我提到的,代码中没有提到它。
它是 .net 2.0,所以没有 Asyncs。
这只是更大应用程序的一部分,因此它是一个 Windows 服务,但我们将其作为 CMD 运行以便能够轻松调试它。主应用程序本身是一个 Windows 窗体桌面应用程序。
如果有帮助,它还使用 COM+ 组件。
我试过[STA] 而不是[MTA]。
也如上所述锁定。
MemoryBarriers 也是如此。
我们仍然遇到问题。
问题基本上是损坏的数据集和对象中不应出现的空值。 它大约每 25-100 次迭代发生一次,因此重现并不简单,但我们专门针对此问题设计了一个测试来尝试重现它。
所有这些都将我们引向线程问题的方向。
回到原来的问题—— 谁可能通过产生这些额外的线程以及我们如何防止这些线程被创建?
请注意标有红色的线程 - 这些是后台线程,据我们所知,代码中没有提及它们。
截图中疑似线程正在主动修改dataset中的cols。问题是 - 调用线程正在执行的 SetColValueOnRow 函数的方法是典型的并且不使用任何类型的线程。
此应用程序的 CPU 亲和性设置为 1 Core [原始解决方法的一部分]
谢谢
编辑:数据库是 oracle 12c,但我们面临的问题发生在写入数据库之前。 它们通常发生在数据集中,其中每隔几次测试迭代就可以擦除整条记录或其中的一些列
【问题讨论】:
-
什么类型的应用程序(winforms,服务,...)
-
这只是更大应用程序的一部分,因此它是一个 Windows 服务,但我们将其作为 CMD 运行以便能够轻松调试它。主应用程序本身是一个 Windows 窗体桌面应用程序。
-
“谁可能通过产生这些额外的线程以及我们如何防止这些线程被创建?”——最初的问题是什么?您的标题是“有没有办法强制应用程序以单线程方式运行?”,这似乎是一个完全不同(且不可行)的问题。一个普通的 .NET 程序有多种原因来创建线程,所以这些可能就是您所看到的。甚至不清楚“强制应用程序作为单线程运行”是什么意思。好像有某种方法可以将多个执行序列塞进一个线程?
-
您可以尝试运行 Visual Studio 的性能测试工具;记录并记下线程自发出现的情况,就像让物理学家彻夜难眠的量子泡沫一样
-
你可以做的是在你的类中添加以下自定义注册代码:stackoverflow.com/questions/5726624/… 但设置“Single”而不是“Apartment”(->所有调用将在初始线程上自动序列化) .然后您必须删除/重新创建您的 COM+ 应用程序。 .NET 的 regsvcs 可能不支持自定义线程模型(它只知道“Both”),因此您可能必须手动创建应用程序(使用“组件服务”)或使用一些 VBS/Powershell 脚本
标签: c# multithreading desktop-application com+