繁体   English   中英

在单独的线程上创建WebBrowser控件

[英]Creating WebBrowser Control on a separate thread

好吧,我有一个包含5个WebBrowser控件的表单,每个控件都打开一个页面并处理DocumentComplete事件,问题是有时事件不会触发。 阅读后,我遇到一个回答,说如果线程繁忙,则不会触发类似NavigatedDocumentComplete类的事件,因此我尝试在单独的线程中创建WebBrowser ,然后将其添加到表单中,这将导致跨线程异常

        new Thread(() =>
        {
            WebBrowser1 = new WebBrowser
            {
                Location = new Point(15, 14),
                MinimumSize = new Size(20, 20),
                Name = "WebBrowser1",
                ScriptErrorsSuppressed = true,
                Size = new Size(250, 370),
                TabIndex = 0,
                Url = new Uri("", UriKind.Relative)
            };

            ((WebBrowser_V1) WebBrowser1.ActiveXInstance).NewWindow += (string u, int f, string n, ref object d, string h, ref bool p) =>
            {
                p = true;
                WebBrowser1.Navigate(u);
            };

            WebBrowser1.DocumentCompleted += async (sender, args) =>
            {
                // Code...
            };

            WebBrowser1.Navigated += (sender, args) =>
            {
                // Code...
            };

            WebBrowser1.Navigate(Service.LinkTL.Find(_ => _.Valid)?.Use()?.Address);

            //Cross-Thread Exception
            base.Invoke(new MethodInvoker(() =>
            {
                Controls.Add(WebBrowser1);
            }));

            Application.Run();
        }) {ApartmentState = ApartmentState.STA}.Start();

我需要WebBrowser控件在窗体中可见,但能够拦截所有触发的事件。

编辑:如果我调用WebBrowser我无法Controls created on one thread cannot be parented to a control on a different thread异常Controls created on one thread cannot be parented to a control on a different thread

您需要检查跨线程操作上的InvokeRequired(请参阅: https ://msdn.microsoft.com/zh-cn/library/system.windows.forms.control.invokerequired( v = vs.110).aspx)。

如果是这样,则需要从代码中调用委托。

 myFormControl1.Invoke(myFormControl1.myDelegate);

典型的模式是:

private void DoFoo() {
    if (myFormControl1.InvokeRequired) {
        myFormControl1.Invoke(new MethodInvoker(() => { DoFoo(); }));
    } else {
        object1.Visible = true;
        object2.Visible = false;
    }
}

此线程讨论了在不弄脏代码的情况下干净实现此方法的方法: 自动化InvokeRequired代码模式

线程中的一个有用答案,显示了一个处理调用的静态方法:

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{

    if (control.InvokeRequired) {
        control.Invoke(action);
    } else {
        action();
    }
}

然后像下面这样定义委托:

richEditControl1.InvokeIfRequired(() =>
{
    // Do anything you want with the control here
    richEditControl1.RtfText = value;
    RtfHelpers.AddMissingStyles(richEditControl1);
});

使用它来完成您的特定问题:

public static class myExtension
{
    public static void InvokeIfRequired(this Control control, MethodInvoker action)
    {
        // See Update 2 for edits Mike de Klerk suggests to insert here.

        if (control.InvokeRequired)
        {
            control.Invoke(action);
        }
        else
        {
            action();
        }
    }
}

// ...

protected WebBrowser WebBrowser1;
public void loadBrowser()
{
    new Thread(() =>
        {

            var WebBrowser1 = new WebBrowser
            {
                Location = new Point(15, 14),
                MinimumSize = new Size(20, 20),
                Name = "WebBrowser1",
                ScriptErrorsSuppressed = true,
                Size = new Size(250, 370),
                TabIndex = 0,


            };
            var form = new Form()
            {
                Name = "Other Form",
                Text = "Thread Start Browser",
                AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F),
                AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font,
                ClientSize = new System.Drawing.Size(284, 261),
            };
            form.Controls.Add(WebBrowser1);
            form.Show();
            //((WebBrowser_V1)WebBrowser1.ActiveXInstance).NewWindow += (string u, int f, string n, ref object d, string h, ref bool p) =>
            //{
            //    p = true;
            //    WebBrowser1.Navigate(u);
            //};

            //WebBrowser1.DocumentCompleted += async (sender, args) =>
            //{
            //    // Code...
            //};

            WebBrowser1.Navigated += (sender, args) =>
            {
                // Code...
            };

            //WebBrowser1.Navigate(Service.LinkTL.Find(_ => _.Valid)?.Use()?.Address);

             WebBrowser1.Navigated += (sender, args) =>
            {
                // Code...
            };

            //WebBrowser1.Navigate(Service.LinkTL.Find(_ => _.Valid)?.Use()?.Address);

            this.InvokeIfRequired(() =>
            {
                this.WebBrowser1 = WebBrowser1;
                this.CreatedBrowser(); 

            });

            Application.Run();
        })

        { ApartmentState = ApartmentState.STA }.Start();
    }
private void Form1_Load(object sender, EventArgs e)
{
    loadBrowser();
}
public void CreatedBrowser()
{
    Console.WriteLine("Created browser");
}
private void btnGo_Click(object sender, EventArgs e)
{
    string url = txtUrl.Text;
    WebBrowser1.InvokeIfRequired(() => WebBrowser1.Navigate(url));
}

这是一个屏幕截图:

WebBrowser在单独的线程上创建

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM