First in Main(), it launches a form called 'MainForm' with Application.Run() method. Application.Run() creates message pump for a UI form, in this case, in main UI thread.
static class Program { ////// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } }
In Form_Load() of MainForm, we create 3 new Forms from 3 different threads.
public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { // Start new UI thread for Form1 Thread thread1 = new Thread(ShowForm1); thread1.Start(); // Start new UI thread for Form2 Thread thread2 = new Thread(() => { Form2 f2 = new Form2(); Application.Run(f2); }); thread2.Start(); // Start new UI thread for Form3 Thread thread3 = new Thread(ShowForm3); thread3.Start(); } void ShowForm1() { // message pump with Application.Run() Application.Run(new Form1()); } void ShowForm3() { Form3 f3 = new Form3(); // Start message pump by using ShowDialog() f3.ShowDialog(); } }
First thread, thread1, runs ShowForm1() function which is simply calls Application.Run() against new Form1 instance. This thread creates new message pump for Form1 and works separately from MainForm.
Second thread, thread2, shows an example of using anonymous delegate to launch Form2. Basically it's the same as ShowForm1().
Third thread, thread3, calls ShowForm3() function where Form3 is launched by using ShowDialog(). If one uses Show() method instead of ShowDialog() here, thread will show the Form3 but then the form will be closed immediately since the thread will exit. ShowDialog begins new message pump for Form3 and will stay until user clicks Close button.
Each UI thread will work separately. Once all forms are closed, the application will be closed.
Building progress bar ui threads in WinForms
ReplyDeleteOMG, I can't believe that starting a new UI Thread was that simple... after everything I have read among Google's results and StackOverflow's Q&As, I thought I would abandon...
ReplyDeleteWhen finally, all I needed to call was Application.Run(myNewFormUIThreaded); !
Thanks for sharing your nice&useful notes Alex!
UI threads should run as AppartmentState.STA to avoid random crashes when using some UI controls or windows COM interops, namely the Clipboard.
ReplyDeleteThis can be set before the thread is started:
thread.SetApartmentState(AppartmentState.STA);