Form.InvokeRequired 在显示表单之前返回false。
我做了一个简单的测试:
Form2 f2 = new Form2();
Thread t = new Thread(new ThreadStart(() => PrintInvokeRequired(f2)));
t.Start();
t.Join();
f2.Show();
t = new Thread(new ThreadStart(() => PrintInvokeRequired(f2)));
t.Start();
t.Join();
借助助手
private void PrintInvokeRequired(Form form)
{
Console.WriteLine("IsHandleCreated: " + form.IsHandleCreated + ", InvokeRequired: " + form.InvokeRequired);
}
输出是
IsHandleCreated:假,InvokeRequired:假
IsHandleCreated:真,InvokeRequired:真
另请注意,这在MSDN 上有一些记录:
如果控件的句柄还没有
存在,InvokeRequired 搜索
控件的父链,直到找到
具有
窗把手。如果没有合适的
可以找到句柄,
InvokeRequired 方法返回 false。
这意味着 InvokeRequired 可以
如果不需要调用,则返回 false
(调用发生在同一个线程上),
或者如果控件是在
不同的线程,但控件的
句柄尚未创建。
在控件的句柄的情况下
尚未创建,您应该
不仅仅是调用属性、方法,
或控件上的事件。这有可能
导致控件的句柄是
在后台线程上创建,
隔离线程上的控件
没有消息泵并制作
应用不稳定。
您可以通过以下方式防范这种情况
还检查的值
IsHandleCreated when InvokeRequired
在后台线程上返回 false。
如果控制手柄尚未
创建,您必须等到它有
在调用 Invoke 或之前创建
开始调用。通常,会发生这种情况
仅在创建后台线程时
在主要形式的构造函数中
对于应用程序(如
Application.Run(新 MainForm()),
在表格显示之前或
Application.Run 已被调用。
您的解决方案是同时检查IsHandleCreated。
编辑:
Handle 可以随时在 WebBrowser 控件内部或外部创建。这不会自动创建父窗体的句柄。
我创建了一个例子:
public Form2()
{
InitializeComponent();
Button button1 = new Button();
this.Controls.Add(button1);
Console.WriteLine("button1: " + button1.IsHandleCreated + " this: " + this.IsHandleCreated);
var tmp = button1.Handle; // Forces the Handle to be created.
Console.WriteLine("button1: " + button1.IsHandleCreated + " this: " + this.IsHandleCreated);
}
输出:
button1: False this: False
button1: True this: False