2

正确的问题

有没有人在单核机器上遇到过这个异常?

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

一些上下文

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

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

有趣的是,超线程 Pentium 并没有表现出这个问题。

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

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

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

以随机间隔,当我提供的 AsyncCallbackStream.BeginRead(...)被调用并且处理程序尝试调用Stream.EndRead(IAsyncResult)时,它会抛出一个IOException声明The I/O operation has been aborted because of either a thread exit or an application request.

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

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

微软倾向于吹嘘这些错误报告是不可重现的。我怀疑这是因为问题只发生在多核系统上,并且像这样的错误报告没有提到 CPU 的数量。

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


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

调查问题的变体 A,我已将问题代码移植到示例应用程序中,并对其进行了精简,直到只剩下线程设置和在一个 CPU 上工作但在两个 CPU 上失败的方法调用。

变体 BI 还没有经过如此测试,因为我不再有任何单核系统。所以我重复这个问题:有没有人在单核平台上看到过这个异常?

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

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

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

4

5 回答 5

2

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

另外:要回答有关如何将应用程序限制为单个 CPU 的问题,您需要将进程关联设置为单个 CPU。请参阅此链接。您也可以在您的进程开始使用任务管理器后执行此操作(右键单击任务管理器中的进程并选择“设置关联...”)

于 2008-11-19T02:07:30.173 回答
2

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

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

于 2008-11-19T07:16:38.083 回答
2

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

因此,当我开始更多地学习代码时,我发现开发它的人对如何正确编写多线程代码一无所知。所有“同步”都是使用 Thread.Sleep() 完成的!线程管理是在“即发即弃”的基础上完成的。有人想停止线程吗?线程.Abort()!该死!令人惊讶的是,这该死的东西竟然在起作用。

我的意思是——去检查你的代码,如果你正在使用一些定制硬件,他们的驱动程序代码。问题就在那里,不在 .NET、Win32 或其他地方。

于 2008-11-19T18:39:08.877 回答
1

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

由于线程退出或应用程序请求,I/O 操作已中止。

我不确定这是否与您的问题相关,但是您是否从可以在操作完成之前终止的线程发出异步操作?

于 2008-11-19T17:39:27.297 回答
1

我在这里完全不知所措。你说你的代码在双核机器上被破坏了,你怀疑是 MS !!!

现在有一天,每台机器都有双核甚至四核。如果 .net 框架在使用双核时遇到任何重大问题,那么为什么 live messenger、live writer 和许多其他 .net 厚应用程序不会经常中断。我相信 SQL Server 2K5 和 2K8 管理工作室也在 .net 中。整个 System.Web 实现在 C# 本身中。整个 Biztalk 编排设计器都在 .net 中

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

你试过SOS吗?尝试这样做......我不太了解,但谷歌为它,你肯定会得到关于使用 SOS 的好资源。

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

于 2008-11-19T18:16:00.390 回答