今天在写一个socket通信的winform小程序,由于socket的receive方法会阻塞线程,所以就使用了多线程解决。但在新建的线程中创建OpenFileDialog并调用其ShowDialog()时,对话框无法弹出。经测试,在winform界面上添加新按钮在其click事件中直接用OpenFileDialog时没有任何问题。
环境: Windows2008R2x64, .Net Framework4.0
文中提到是因为主线程必须是单线程单元, 应在Main函数上加 [STAThread] 属性,但不知是不是我用的Net Framework4.0的缘故,winform在创建时Main函数就已经有[STAThread] 属性了,所以这种方式貌似不能解决我的问题。
提到要用新建OpenFileDialog的线程的SetApartmentState()方法设置ApartmentState值为ApartmentState.STA,设置此线程为单线程单元。
代码如下所示:
Thread threadRec = new Thread(Rec); threadRec.SetApartmentState(ApartmentState.STA);threadRec.IsBackground = true; threadRec.Start();
我的问题因此得到解决,希望对大家也有帮助。
MSDN上关于ApartmentState值的备注如下:
单元是进程内部具有相同线程访问要求的对象的逻辑容器。同一单元中的所有对象都可以接收从该单元中的任何线程发出的调用。.NET Framework 不使用单元,托管对象自己负责以线程安全的方式使用所有共享资源。 由于 COM 类使用单元,因此公共语言运行时需要在 COM 互操作 的情况下调用 COM 对象时创建并初始化一个单元。托管线程可以创建并进入只允许有一个线程的单线程单元 (STA) 或者包含一个或多个线程的多线程单元 (MTA)。通过将线程的 ApartmentState 属性设置为 ApartmentState 枚举值之一,可以控制所创建的单元的类型。由于给定线程只能初始化 COM 单元一次,因此在第一次调用非托管代码之后就不能更改单元类型。