[英]Creating WebBrowser Control on a separate thread
好吧,我有一个包含5个WebBrowser
控件的表单,每个控件都打开一个页面并处理DocumentComplete
事件,问题是有时事件不会触发。 阅读后,我遇到一个回答,说如果线程繁忙,则不会触发类似Navigated
, DocumentComplete
类的事件,因此我尝试在单独的线程中创建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));
}
这是一个屏幕截图:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.