我有一个程序,它使用控制台和GUI来完成程序的重要方面。我认为这两个部分都使用相同的线程。
问题在于我正在使用带有输出的万用表,并且从程序发送命令来接收数据 - 它使用SCPI,这些命令通过控制台运行。
问题是,每当我向万用表发送命令时,它会使程序无响应,直到它收到数据为止,我知道为什么,我也知道如何修复它,但我想知道是否有更好的方式。
目前我正在更改运行GUI的默认线程:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread applicationThread = new Thread(() => Application.Run(new Form1()));
applicationThread.SetApartmentState(ApartmentState.STA);
applicationThread.Start();
}
当我向仪表发送命令时,这会阻止程序无响应,但我不能100%确定这是否会产生我还没有看到的任何其他问题?
我的问题是:
答案 0 :(得分:3)
[STAThread]
static void Main()
这是非常不明智的,你打破了STAThread合同。其中规定您必须抽取消息循环。 Application.Run()在.NET程序中。您为显示UI但不是主线程的线程正确执行了此操作。你可能用来与仪表交谈的那个。
最糟糕的问题是,它很容易看起来就像你会逃脱它一样。但它是一颗滴答作响的定时炸弹,随时准备在你脸上爆炸。不良行为的范围从任意死锁,特别是使.NET程序的终结器线程挂起的令人讨厌的类型。当CLR尝试释放COM互操作包装时发生。非常难以诊断,当程序内存不足时,程序最终会崩溃。需要一段时间,总是比耐心测试应用程序更长。对于仪表对象本身的随机不当行为,通常通过调用对象死锁或未引发预期事件的对象来诊断。
终结器线程死锁肯定是最糟糕的问题,足以让你改变这个问题。专注于真正的问题,仪表代码是行为不端的。给它一个安全的避风港,一个正确构造的STA螺纹泵。你会在this post找到样板代码。或者只是将属性更改为[MTAThread],这会强制COM自己为COM对象提供安全的避风港。但是最好把它的号角拿走,这样你就可以知道正在发生什么,而不是依赖于不可摧毁的黑魔法。
我还强烈建议对该组件的供应商或作者进行支持。单元线程COM服务器不应该以这种方式运行。有点不对劲。