Reputation: 1433
I am using the following code to open a form in a new thread:
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();
}
But the newly created form isn't TopMost even though I set it to true.
How can I make a form in a thread TopMost ?
Upvotes: 9
Views: 3689
Reputation: 74
You're creating a new thread that is different than the UI thread. the UI components must be updated on the same thread that created them, which is typically the main UI thread. If you attempt to update a UI element from a background thread, you will get a InvalidOperationException because the UI framework enforces thread affinity for UI components.
The Invoke method is used to marshal the call to the UI thread from a different thread. When you use Invoke, it essentially schedules the method to be executed on the UI thread, ensuring that thread safety rules are respected.
Here’s why you need to use Invoke:
Note: Although the form itself is created in the other thread, the UI thread is still used to show the form.
Instead of calling ShowDialog directly, try using this.Invoke to gain ownership of the form.
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(); });
}
Upvotes: -2
Reputation: 98746
Just ran into this problem myself. It seems that if the form has an Owner
, then TopMost
works as expected. If the owning form was created on another thread, though, it's a little tricky to set. Here's what I used:
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);
Upvotes: 2
Reputation: 2321
Usually you don't need another thread, you open the form as usual in modal or non modal mode, if the form needs to do a heavy process then you do the process inside a thread.
Specific to your question one option is to run the form from an Application.Run as described 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);
}
}
}
That will launch a new thread with its own message pump and will keep it as a TopMost form.
Upvotes: 5