线程中的TopMost窗体?

9

我正在使用以下代码在新线程中打开一个表单:

private void button1_Click(object sender, EventArgs e)
{

    Thread thread = new Thread(ThreadProc);
    thread.Start();
}


public void ThreadProc()
{

    Form form = new Form();
    form.TopMost = true;
    form.ShowDialog();
}

但是即使我将新创建的表单设置为true,它也不是最上层的。

如何使线程中的表单成为最上层?

3个回答

5
通常情况下,您不需要另一个线程,您可以像通常一样以模态或非模态模式打开表单,如果表单需要执行繁重的过程,则在线程内部执行该过程。

针对您的问题,一种选项是按照此处所述,在Application.Run中运行表单。
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread = new Thread(ThreadProc);
        thread.Start();
    }


    public void ThreadProc()
    {
        using (Form1 _form = new Form1())
        {
            _form.TopMost = true;
            Application.Run(_form);
        }
    }
}

这将启动一个新的线程,拥有自己的消息队列,并将其保持为最顶层的窗体。


好的,那应该会在新线程中创建一个窗体,并允许它成为最顶层的窗体吗?我会试一下的!谢谢。 - syncis
那其实不起作用,因为如果我在新线程中运行“Application.Run(_form);”,它仍然在一个新线程中,问题仍然存在,它不会成为最顶层,并且如果我尝试启动“Application.Run(_form);”而不启动新线程(在主线程中启动),那么我会得到异常“在单个线程上启动第二个消息循环不是有效操作。” - syncis
我修改了一个更完整的代码,它为我产生了预期的结果。 - Cristian T

2

我自己也遇到过这个问题。看起来,如果表单有一个Owner,那么TopMost就能按预期工作。但是,如果所属的表单在另一个线程上创建,设置会比较棘手。以下是我使用的代码:

var form = new Form();

form.Shown += (sender, e) => {
    Control.CheckForIllegalCrossThreadCalls = false;
    form.Owner = /* Owning form here */;
    form.CenterToParent();      // Not necessary
    Control.CheckForIllegalCrossThreadCalls = true;

    form.TopMost = true;        // Works now!
};

Application.Run(form);

你刚刚拯救了这一天。非常感谢 :D :D - MarshallOfSound

-1

尝试使用this.Invoke获取窗体的所有权,而不是直接调用ShowDialog。

private void button1_Click(object sender, EventArgs e)
{

    Thread thread = new Thread(ThreadProc);
    thread.Start();
}


public void ThreadProc()
{

    Form form = new Form();
    form.TopMost = true;
    this.Invoke((Action)delegate() { form.ShowDialog(); });
}

1
你的回答相当不具信息性。考虑添加为什么这可能是解决方案。 - David L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接