English 中文(简体)
通过线程在另一个窗体上将窗体显示为对话框
原标题:Show a form as a dialog on another form via thread

以下代码给出了“跨线程操作”异常。只是因为“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"]);
        }));
    }
}
}
最佳回答

网络浏览器。Navigate()调用有问题。这将强制创建控件的本机窗口句柄,并且这种情况发生在工作线程上。一段时间后,您将强制使用ShowDialog()调用创建窗体的本机窗口。但由于调用了Invoke(),这种情况会发生在另一个线程上,即主UI线程上。

现在出现了不匹配,表单的窗口由主线程拥有,但浏览器的窗口由工作线程拥有。Winforms介入以提醒您这是非法的,子窗口必须与容器窗口由同一线程拥有。解决方法是将Navigate调用移动到匿名方法内部。

您之所以得到这段代码,可能是因为当您尝试在不使用Invoke()调用的情况下显示对话框时,还得到了一个IllegalOperationException。如果您真的想在工作线程上运行对话框,这将是正常的做法。Winforms引发异常,因为它不希望窗口的所有者成为另一个线程上的窗口。这在Windows中实际上是合法的,Winforms摸索着检查。

您可以通过钉选SetParent()来解决此问题。字节我的舌头,在这种非常特殊的情况下,永远不要在任何其他情况下这样做,通过临时设置控制。CheckForIllegalCrossThreadCall为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();
问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...