While it is not possible to create a form on one thread, and display it using another thread, it is certainly possible to create a form in a non main GUI thread. The current accepted answer seems to say this is not possible.
Windows Forms enforces the Single Threaded Apartment model. In summary this means that there can only be one Window message loop per thread and vice versa. Also, if for example threadA wants to interact with the message loop of threadB, it must marshal the call through mechanisms such as BeginInvoke.
However, if you create a new thread and provide it with it's own message loop, that thread will happily process events independently until it is told to end the message loop.
So to demonstrate, below is Windows Forms code for creating and displaying a form on a non GUI thread:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = Thread.CurrentThread.ManagedThreadId.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
ThreadStart ts = new ThreadStart(OpenForm);
Thread t = new Thread(ts);
t.IsBackground=false;
t.Start();
}
private void OpenForm()
{
Form2 f2 = new Form2();
f2.ShowDialog();
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = Thread.CurrentThread.ManagedThreadId.ToString() ;
}
}
The OpenForm method runs in a new thread and creates an instance of Form2.
Form2 is actually given it's own separate message loop by calling ShowDialog(). If you were to call Show() instead, no message loop would be provided and Form2 would close immediately.
Also, if you try accessing Form1 within OpenForm() (such as using 'this') you will receive a runtime error as you are trying to do cross-thread UI access.
The t.IsBackground=false
sets the thread as a foreground thread. We need a foreground thread because background threads are killed immediately when the main form is closed without first calling FormClosing or FormClosed events.
Apart from these points, Form2 can now be used just like any other form. You'll notice that Form1 is still happily running as usual with it's own message lopp. This means you can click on the button and create multiple instances of Form2, each with their own separate message loop and thread.
You do need to be careful about cross Form access which is now actually cross-thread. You also need to ensure that you handle closing of the main form to ensure any non main thread forms are closed correctly.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…