Dmi*_*nov 7 .net webbrowser-control invokerequired winforms
这怎么可能?我有Windows窗体控件,派生自System.Windows.Forms.Form,此窗体中包含WebBrowser控件.Webbrowser对象实例是在form的构造函数中创建的(在InitializeComponent()方法中).然后在后台线程中我使用WebBrowser的内容进行操作,我发现在某些情况下Form.InvokeRequired == false,而WebBrowser.InvokeRequired == true.怎么会这样?
Form.InvokeRequiredfalse在显示表单之前返回.
我做了一个简单的测试:
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();
Run Code Online (Sandbox Code Playgroud)
与帮助者
private void PrintInvokeRequired(Form form)
{
Console.WriteLine("IsHandleCreated: " + form.IsHandleCreated + ", InvokeRequired: " + form.InvokeRequired);
}
Run Code Online (Sandbox Code Playgroud)
输出是
IsHandleCreated:False,InvokeRequired:False
IsHandleCreated:True,InvokeRequired:True
另请注意,这在MSDN上有所记录:
如果控件的句柄尚不存在,InvokeRequired将向上搜索控件的父链,直到找到具有窗口句柄的控件或表单.如果找不到合适的句柄,则InvokeRequired方法返回false.
这意味着如果不需要Invoke(调用发生在同一个线程上),或者控件是在另一个线程上创建但尚未创建控件的句柄,则InvokeRequired可以返回false.
如果尚未创建控件的句柄,则不应简单地在控件上调用属性,方法或事件.这可能导致在后台线程上创建控件的句柄,在没有消息泵的情况下隔离线程上的控件并使应用程序不稳定.
当InvokeRequired在后台线程上返回false时,还可以通过检查IsHandleCreated的值来防止这种情况.如果尚未创建控件句柄,则必须等到创建它之后再调用Invoke或BeginInvoke.通常,只有在应用程序的主要表单的构造函数中创建后台线程(如在Application.Run(new MainForm())中,在显示表单或调用Application.Run之前,才会发生这种情况.
你的解决方案是检查IsHandleCreated.
编辑:
该Handle可以在任何时间在浏览器控件或外部内部创建.这不会自动创建父窗体的句柄.
我创建了一个例子:
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);
}
Run Code Online (Sandbox Code Playgroud)
与输出:
button1:False this:False
button1:True this:False