最近遇到这种情况,我想在另一个线程(不是主/UI线程)上显示一个表单。我使用了线程池线程。该窗体托管了一个 RCW(用于 COM 组件)。实例化表单给了我一个线程必须是 STA 的异常。我试图将公寓状态设置为 STA。但是,那也没有用。我最终明确地创建了一个线程并且成功了(我使用了 ShowDialog 并且不需要创建一个 meesage 泵)。
编辑:
我知道线程池线程是 MTA。但是,为什么不能设置成STA呢? 只是对此感到好奇。
另一个突然出现在我脑海中的问题:为什么我们在使用 Showdialog()(显示表单)时不需要消息泵
最佳答案
通过调用 CoInitializeEx() 选择公寓。线程池中的线程已经进行了该调用,不可能在该调用之后更改单元。
线程池选择 MTA 是有道理的,毕竟它是作为工作线程使用的,不应被需要编码的方法调用阻塞。选择单线程单元还有一个额外的消息循环要求。一些您永远不会想到线程池线程会做的事情。
消息循环是必需的,因为它是 COM 用于编码在另一个线程上进行的调用的工具。该调用必须在 STA 线程中“注入(inject)”,只有当线程处于已知的静止状态时才有可能。如果不是,这样的调用会导致重大的重入问题。即使线程正在循环中,它有时也会这样做。
您不需要使用 Application.Run() 自己创建消息循环,因为 ShowDialog() 会启动它自己的消息循环。这就是它获得模态的方式。该嵌套循环在对话框关闭后立即退出。
关于c# - 为什么我们不能更改 ThreadPool 线程的单元状态,为什么我们在使用 ShowDialog 时不需要消息泵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1280867/