我正在使用以下代码在新线程中打开表单:
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();
}
但是新创建的表单不是 TopMost,即使我将其设置为 true。
如何在线程 TopMost 中制作表单?
通常你不需要另一个线程,你可以像往常一样在模态或非模态模式下打开表单,如果表单需要执行繁重的过程,那么你可以在线程内执行该过程。
针对您的问题,一种选择是从 Application.Run 运行表单,如here所述。
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);
}
}
}
这将启动一个带有自己的消息泵的新线程,并将其保留为 TopMost 形式。
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);
Invoke 方法用于封送来自不同线程的对 UI 线程的调用。当您使用 Invoke 时,它本质上是安排要在 UI 线程上执行的方法,确保遵守线程安全规则。
这就是您需要使用 Invoke 的原因:
不要直接调用 ShowDialog,而是尝试使用 this.Invoke 来获得表单的所有权。
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(); });
}