实现带EventHandler的List<Form>作为MDI子窗体时遇赋值错误求助
问题分析与解决
错误根源
从堆栈信息可以明确:你在非UI线程中操作Windows Forms控件。最后一行的_StageTwoReaderServer是后台线程,事件从这里触发后,后续的窗体创建、MdiParent赋值等操作都在非UI线程执行,而WinForms要求所有UI控件的操作必须在创建它们的线程(即UI主线程)中进行,这才导致了Control.get_Handle()的报错——和你用不用List<T>存储窗体完全无关。
解决方案
通过Control.Invoke或BeginInvoke将UI操作切换到UI线程执行即可,不需要替换List<T>集合。
修改后的主窗体代码示例
假设你的JoinRoom方法是事件处理的入口,修改如下:
static List<frmWindow> Window = new List<frmWindow>(); private void JoinRoom(eventData e) { // 判断当前是否在UI线程,不在则切换 if (InvokeRequired) { Invoke(new Action<eventData>(JoinRoom), e); return; } // 以下代码在UI线程执行,安全操作窗体 var newWindow = new frmWindow("windowName", 0); Window.Add(newWindow); newWindow.MdiParent = this; newWindow.Show(); }
额外说明
- 之前非
List<T>形式的代码正常,大概率是因为那些操作刚好在UI线程执行,没有触发跨线程场景。 - 所有涉及UI控件的操作(包括窗体创建、属性赋值、显示)都必须放在UI线程,后续如果在
frmWindow里有事件处理涉及UI更新,同样要检查InvokeRequired。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

