.net - 窗体的 InvokeRequired == false 和包含的控件的 InvokeRequired == true

标签 .net winforms webbrowser-control invokerequired

这怎么可能?我有 Windows 窗体控件,从 System.Windows.Forms.Form 派生,WebBrowser 控件包含在此窗体中。 Webbrowser 对象实例是在表单的构造函数中创建的(在 InitializeComponent() 方法中)。然后在后台线程中操作 WebBrowser 的内容,我发现在某些情况下 Form.InvokeRequired == false,而 WebBrowser.InvokeRequired == true。怎么会这样?

最佳答案

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();

与 helper
private void PrintInvokeRequired(Form form)
{
    Console.WriteLine("IsHandleCreated: " + form.IsHandleCreated + ", InvokeRequired: " + form.InvokeRequired);
}

输出是

IsHandleCreated: False, InvokeRequired: False
IsHandleCreated: True, InvokeRequired: True



另请注意,这在 MSDN 上有所记录。 :

If the control's handle does not yet exist, InvokeRequired searches up the control's parent chain until it finds a control or form that does have a window handle. If no appropriate handle can be found, the InvokeRequired method returns false.

This means that InvokeRequired can return false if Invoke is not required (the call occurs on the same thread), or if the control was created on a different thread but the control's handle has not yet been created.

In the case where the control's handle has not yet been created, you should not simply call properties, methods, or events on the control. This might cause the control's handle to be created on the background thread, isolating the control on a thread without a message pump and making the application unstable.

You can protect against this case by also checking the value of IsHandleCreated when InvokeRequired returns false on a background thread. If the control handle has not yet been created, you must wait until it has been created before calling Invoke or BeginInvoke. Typically, this happens only if a background thread is created in the constructor of the primary form for the application (as in Application.Run(new MainForm()), before the form has been shown or Application.Run has been called.



您的解决方案是还检查 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

关于.net - 窗体的 InvokeRequired == false 和包含的控件的 InvokeRequired == true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4013954/

相关文章:

c# - 通过 HtmlDocument.All 集合的迭代在引用的样式表处停止?

c# - 设置默认值后,从 WebBrowser 控件打印到错误的打印机

c# - 在 ASP.NET MVC 3 中初始化一个空白的 dbSet

.net - 属于T还是属于TEntity?

c# - IEnumerable<T>.Last() 是否针对 List<T> 进行了优化?

c# - .Net 简单正则表达式二次复杂度

C# WinForms : How to know/detect if tooltip is being displayed/shown

c# - 有什么方法可以在 MS 图表中的 Y2 轴上显示折线图?

c# - 窗体上的控件未在设计器中显示

c# - WebBrowser 组件不显示 CSS 3