Microsoft.NET和Doom的多核CPU

时间:2008-11-19 01:45:52

标签: .net multithreading multicore ioexception

正确的问题

是否有人在单核计算机上遇到此异常?

  

The I/O operation has been aborted because of either a thread exit or an application request.

某些背景

在单CPU系统上,一次只执行一条MSIL指令,尽管有线程。在操作之间,运行时可以进行内务管理。

引入第二个CPU(或第二个核心),可以在运行时执行内务处理时执行操作。因此,在多核环境中执行时,在单个CPU机器上完美运行的代码可能会崩溃 - 甚至会导致蓝屏。

有趣的是,HyperThreaded Pentiums 表明了问题。

我的示例代码在单核上完美运行,并且在多核CPU上实现了分片。它在某处,但我仍在努力找到它。它的要点是,当它被实现为访问者模式时,它会在不可预测的迭代次数之后剥落,但是将方法移动到访问者操作的对象使得问题消失。

对我而言,这表明框架具有某种用于解析对象引用的内部哈希表,并且在多核系统上存在关于访问它的竞争条件。

我目前还有使用APM处理串行通信的代码。它曾经在我的USB串口适配器的虚拟comport驱动程序中间歇性地进行了蓝屏,但我通过在每Thread.Sleep(0)

之后执行Stream.EndRead(IAsyncResult)来解决这个问题。

在随机的时间间隔内,当调用我提供给Stream.BeginRead(...)的AsyncCallback并且处理程序尝试调用Stream.EndRead(IAsyncResult)时,它会抛出IOException表示The I/O operation has been aborted because of either a thread exit or an application request.

我怀疑这也是多核相关的,某种内部错误正在杀死等待线程,导致这种行为。如果我对此是对的,那么该框架在多核环境的背景下存在严重缺陷。虽然有一些解决方法,例如我提到的,但您不能总是应用它们,因为有时它们需要在内部其他框架代码中应用。

例如,如果您在网上搜索上述IOException,您会发现它会影响那些显然甚至不知道他们使用多个线程的人编写的代码,因为它发生在框架便利包装器的封面下。

微软倾向于将这些错误报告视为不可再生的。我怀疑这是因为问题只发生在多核系统上,而像this one这样的错误报告没有提到CPU的数量。

所以......请帮我解决问题。如果我是对的,我将不得不用可重复的测试用例来证明它,因为我认为错误的是在框架和运行时都需要错误修正。


有人认为问题更可能是我的代码而不是框架。

调查问题的变体A,我已将问题代码移植到示例应用程序中并将其减少,直到剩下的只有线程设置和方法调用在一个CPU上运行而在两个上失败。

变体B我没有经过测试,因为我不再拥有任何单核系统。所以我重复一个问题:有没有人在单个核心平台上看过这个例外?

不幸的是,没有人可以证实我的怀疑,只能反驳它。

告诉我自己容易犯错是没有用的,我已经意识到了这一点。

如果您知道将.NET应用程序固定到单个CPU的方法,那么解决这个问题会非常方便。 ---感谢VM的建议。我会做到这一点,好的电话。

5 个答案:

答案 0 :(得分:2)

根据您的描述,我倾向于责怪COM端口驱动程序。它的驱动力是在多核时代之前开发出来的吗?我曾经遇到过这样一个类似问题的设备,后来的驱动程序修订版得到了解决。

添加:要回答有关如何将应用程序限制为单个CPU的问题,您需要将进程关联性设置为单个CPU。见this link。您也可以在使用任务管理器开始流程后执行此操作(右键单击任务管理器中的流程并选择“设置亲和力...”)

答案 1 :(得分:2)

蓝屏不仅仅是因为应用程序或框架中的错误。蓝屏需要内核模式的“帮助”。你的一个问题是驱动程序有缺陷,无论编码有缺陷的驱动程序是哪个“时代”。

关于一个线程关闭端口而另一个线程仍在使用它的可能性,我认为这可能与框架内务管理中的一些着名错误有关。我认为这些错误并不依赖于核心数量,但是当核心数量增加时,受这些漏洞攻击的频率可能会增加。尝试添加GC.KeepAlive调用以防止框架过早删除您的端口。

答案 2 :(得分:2)

我目前正在重写我们的应用程序中使用的整个文件传输堆栈。通过与其他工作人员的对话,我知道几年前,当单核笔记本电脑和低速连接用于生产时,它有点工作。现在每个人都转向双核和高速互联网,整个软件显示出不可预测的结果。

所以,当我开始更多地学习代码时,我发现开发它的人,对如何正确编写多线程代码没有一个想法。所有“同步”都是使用Thread.Sleep()完成的!线程管理是在“即发即忘”的基础上完成的。有人想停止线程吗? Thread.Abort的()!该死!这该死的事情一点都很令人惊讶。

我的观点是 - 去检查你的代码,如果你正在使用一些自定义硬件,他们的驱动程序代码。问题在于,不是在.NET,Win32或其他地方。

答案 3 :(得分:1)

在Vista之前,任何发出它的线程终止时正在进行的异步IO都会终止。这往往会给出您报告的错误,即

  

I / O操作已中止   因为线程退出或者是   申请要求。

我不确定这是否与你的问题有任何关系,但是你是否从一个可以在操作完成之前终止的线程发出异步操作?

答案 4 :(得分:1)

我完全失去了言语。你告诉你的代码在双核机器上破解了,你怀疑是MS的!

现在有一天,每台机器都有双核甚至四核。如果.net框架在使用双核时遇到任何重大问题,那么为什么直播信使,现场编写器和许多其他.net厚应用程序不会频繁破解。我相信SQL Server 2K5和2K8管理工作室也在.net中。整个System.Web实现在C#本身。整个Biztalk业务流程设计器位于.net

现在来点。您的应用程序似乎具有多线程和大量异步调用上下。你有灵活配置没有。您的应用程序中的线程?如果是,可以将线程限制为1然后进行测试。多线程导致的错误很难追踪。

你试过SOS吗?尝试这样做......我不太了解谷歌,你肯定会获得有关SOS用法的良好资源。

作为最后的手段,打开一个MS支持案例。你需要对他们很少耐心,因为一开始他们会从所有愚蠢的问题开始:)。祝你好运。