我正在使用管道将遗留应用程序(用 COBOL 编写)与我们的 .NET 新应用程序连接起来。这个想法很简单:遗留程序(我的 ERP 菜单)在流上写入一些参数,.NET 应用程序通过Console.In
流读取它并启动一个新线程,打开请求的屏幕。这是 .NET 方面的一个片段,说明了这个想法是如何工作的:
<STAThread(), LoaderOptimization(LoaderOptimization.MultiDomain)>
Shared Sub Main()
If Environment.GetCommandLineArgs(1) = "PIPE"
While True
Dim pipeParam as String
Try
pipeParam = Console.In.ReadLine()
Catch e as Exception
Exit Sub
End Try
' Deal with parameters here
If pipeParam = "END"
Dim newThread as New Threading.Thread(Sub()
' Create a new AppDomain and Loads the menu option, generally a Winforms form.
End Sub)
newThread.Start()
End If
End While
End If
End Sub
一切都很好,很容易......直到今天。我在我的客户端环境(Windows Server 2003)中部署了这个解决方案,并且碰巧没有执行任何请求的线程,除非被调用的进程(COBOL)被终止(Console.In
即被强制关闭)。从那时起,所有请求的 winform 都将开始显示并按预期运行。
用日志挖掘这种奇怪的行为,我发现线程正常执行,直到执行IDictionary.ContainsKey()
语句(或其他需要本机代码执行的方法)。此时,线程冻结/休眠。
如果我将线程创建限制为三个,那么每个创建的线程都会挂起,直到第三个线程,即Console.In.ReadLine
不再执行的时候。
我应该尝试什么?有什么建议吗?
更多信息:到目前为止,我发现的最接近的方向是 Hans Passant 在这个问题中的回答: Interface freezes in multi-threaded c# application(.NET SystemEvents 恰好出现在我的调试器线程列表中,但我无法解决我对建议的解决方案的问题)。
更新新闻
我可以通过等待子线程完成加载Form
. 这个“准备就绪”信号通过AppDomain.SetData()
和传递AppDomain.GetData()
。不知何故,在创建表单后,当主线程继续时,子线程不再冻结Console.ReadLine
。虽然问题解决了,但我对此很感兴趣。我试图在“尽可能简单”的测试用例中重现这一点。
更多细节
- 入口点 .exe 编译为 32 位。所有其他库都是“AnyCpu”。问题发生在 32 位(我的客户端)和 64 位(我的开发)机器(都是 windows Server 2003)上。
- 更新
Sub Main()
了上述代码段中的属性。 - 试图将其放入
Console.ReadLine
工作线程中。没有解决(见下图)。 - COBOL 应用程序不会冻结,因为它是在单独的 OS 进程中执行的。管道恰好是我的 IPC 方法。在这种情况下,COBOL 应用程序只写入参数,不等待响应。
- 堆栈跟踪如下图所示(线程
PRX001235
在连接到数据库之前和有效加载表单之前反序列化 xml 配置文件 - 在这种情况下,似乎仍在托管代码中 - 有时PRX001235
线程会在本机代码中冻结试图连接到数据库):