c# – 通过线程在另一个表单上显示一个表单作为对话框
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 通过线程在另一个表单上显示一个表单作为对话框,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3004字,纯文字阅读大概需要5分钟。
内容图文
以下代码给出了“跨线程操作”异常.仅仅因为“form2.ResumeLayout(false)”.如果这个陈述被评论,我看不到浏览器的形式.我知道ResumeLayout(false)的需要,但有解决方案吗?
namespace WindowsFormsApplication1
{
public partial class Form1: Form
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{ if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); }
private System.Windows.Forms.Button button1;
public Form1()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
this.button1.Location = new System.Drawing.Point(64, 47);
this.button1.Text = this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.Click += new System.EventHandler(this.button1_Click);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.button1);
this.Text = this.Name = "Form1";
this.ResumeLayout(false);
}
private void button1_Click(object sender, EventArgs e)
{
Class1 clss = new Class1();
clss.startme();
}
}
class Class1
{
public void startme()
{
Thread thread = new Thread(new ParameterizedThreadStart(Run));
thread.SetApartmentState(ApartmentState.STA);
thread.Start(null);
}
private void Run(object j)
{
WebBrowser webBrowser1 = new WebBrowser();
webBrowser1.Dock = DockStyle.Fill;
webBrowser1.Navigate("https://dshift.sharepoint.com");
Form form2 = new Form();
form2.SuspendLayout();
form2.Controls.Add(webBrowser1);
form2.ResumeLayout(false);
Application.OpenForms["Form1"].Invoke(new MethodInvoker(delegate
{
form2.ShowDialog(Application.OpenForms["Form1"]);
}));
}
}
}
解决方法:
WebBrowser.Navigate()调用是问题所在.这会强制创建控件的本机窗口句柄,并在工作线程上发生.一段时间后,您强制使用ShowDialog()调用创建表单的本机窗口.但这发生在另一个线程上,主要的UI线程得益于Invoke()调用.
现在存在不匹配,表单的窗口由主线程拥有,但浏览器的窗口由工作线程拥有. Winforms步骤提醒您这是非法的,子窗口必须由与容器窗口相同的线程拥有.解决方法是在匿名方法内移动Navigate调用.
您可能已经到达此代码,因为当您尝试在没有调用Invoke()的情况下显示对话框时,您也遇到了IllegalOperationException.如果你真的想在工作线程上运行对话框,这将是正常的事情. Winforms引发异常,因为它不喜欢窗口的所有者是另一个线程上的窗口.这在Windows中实际上是合法的,Winforms摸索了支票.
你可以通过pinvoking SetParent()来解决这个问题.在这个非常特殊的情况下,通过临时将Control.CheckForIllegalCrossThreadCalls设置为false,在任何其他情况下都不会这样做.暂时强调.需要额外的工作来确保表单实际上是主线程上窗口的模态,并在对话框消失之前重新启用它:
var owner = Application.OpenForms["Form1"];
form2.Load += delegate {
// NOTE: just as a workaround for the Owner bug!!
Control.CheckForIllegalCrossThreadCalls = false;
form2.Owner = owner;
Control.CheckForIllegalCrossThreadCalls = true;
owner.BeginInvoke(new Action(() => owner.Enabled = false));
};
form2.FormClosing += new FormClosingEventHandler((s, ea) => {
if (!ea.Cancel) {
owner.Invoke(new Action(() => owner.Enabled = true));
form2.Owner = null;
}
});
form2.ShowDialog();
内容总结
以上是互联网集市为您收集整理的c# – 通过线程在另一个表单上显示一个表单作为对话框全部内容,希望文章能够帮你解决c# – 通过线程在另一个表单上显示一个表单作为对话框所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。