任何人都可以解释一下这可能发生的原因吗?
我完全了解编程时考虑到线程安全性,你可以看到我通过表单InvokeRequired检查UI更新,检查一切,一切都工作正常,没有任何修改来打破这个,我知道,现在突然就像我正在编写应用程序的其他部分(可能在一个阶段添加到此方法?我只是不记得了)我不好意思,收到此错误:
首先,如果InvokeRequired = true,那应该意味着执行了BeginInvoke(),方法是[队列]重新调用,而InvokeRequired应该等于false?
我不应该收到这个例外,因为它应该照顾吗?
希望听到一些多线程大师:)
格雷厄姆
我怀疑InvokedRevoked可能会骗你.WinForm控件推迟创建Control的底层Win32 HWND,直到方法调用实际需要它为止.如果尚未创建HWND,InvokeRequired将返回false.
有关详细说明,请参阅:"神秘挂起或InvokeRequired的大骗局"
如果后台线程在UI线程导致控件懒惰地创建其HWND 之前查询InvokeRequired ,则InvokeRequired将(错误地)告诉您的后台线程它不需要使用Invoke()将控制权传递回UI线程.然后后台线程访问Control,BAM!"InvalidOperationException:跨线程操作无效!"
UI线程可以手动强制Control创建其HWND句柄,因此Control.InvokeRequired将知道UI线程是Control的所有者:
Control control = new Control(); IntPtr handle = control.Handle; // if you ask for HWND, it will be created
大多数人看到这个错误并看到一件事,"你没有从主UI线程访问这个控件." 实际上,如果需要,您可以拥有100个UI线程(此行为未定义,但受支持).机会是panelMain是在不同的线程上创建的(this); 我看不到代码 - 但看起来你正在你的工作者/线程中创建它.
要确认行为,请尝试以下操作:
Action addAction = new Action ( new delegate { panelMain.Controls.Add(UCLoadingScreen); } ) if(panelMain.InvokeRequired) { panelMain.Invoke(addAction); // Breakpoint here. } else { addAction(); }
准备好一个不同的错误(一个不同的线程上的子控件,它的父母,不知道你会得到什么错误,但我很确定你会.)这不是解决方法.
然而工厂会解决这个问题:
public void CreateControl() where T : new() { if(InvokeRequired) { return (T)Invoke(new Func (CreateControl ())); } return new T(); }
编辑:panelMain可能不是线程'违规者',正如我所说,来自不同线程的父控制导致高度不确定的行为.确保所有控件都是在主窗体的主题的上下文中创建的.