none
How to create a winform app with two UI threads RRS feed

  • Question

  • Hi everyone,

    As the title says, how can I create one winform app with 2 UI threads. I need to do this, lets assume that one UI thread will be for the main form, and the other one will be for another form that behaves kind of like a splash screen. I haven't been able to find any code that details how to create two UI threads.

     

    Thanks.

    Saturday, November 12, 2011 12:36 AM

Answers

  • In general, this is a bad idea -

     

    However, if you need to do it, you can just make a thread, mark it with the STA apartment model, and start a new windows forms message loop:

     

    Thread thread = new Thread( () =>
       {
             var yourForm = new SplashForm();
             Application.Run(yourForm);
       });
    thread.ApartmentState = ApartmentState.STA;
    thread.Start();
    



    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Saturday, November 12, 2011 1:19 AM
    Moderator
  • Addition to Jr, you also can use this way:

          Thread thread = new Thread(ShowForm2);
          thread.Start();
    
       void ShowForm2()
       {
          Form2 f2 = new Form2();
          //ShowDialog will create a separated Message loop, UI thread.
          f2.ShowDialog(); 
       }
    
    Have a nice weekend!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us
    Sunday, November 13, 2011 8:54 AM
    Moderator
  • using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
          BackgroundWorker bgw = new BackgroundWorker();
          bgw.DoWork += bgw_DoWork;
          bgw.RunWorkerAsync();
        }
        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
          Form frm2 = new Form();
          frm2.Text = "Form2";
          frm2.ShowDialog();
        }
      }
    }
    
    

    Sunday, November 13, 2011 9:44 PM
  • kalamantina,
    new Thread(() => { new Form2().ShowDialog(); }).Start();
    new Thread(() => { Application.Run(new Form3()); }).Start();
    

    Both of them is create a new UI thread, a new message loop, so they will not affect the first Form, they will run separately even though you closed the first Form.

    For the ShowDialog behavior you mentioned is in the same thread, the first Form will be operated after you close the second Form. But in this code line, it is just like you boot the Form in a Console application, it helps you create a new message loop in the new UI thread.

    So you can use them everywhere.

    If there's any concern, please feel free to let me know.

    Have a nice weekend!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us
    Monday, November 14, 2011 5:43 AM
    Moderator

All replies

  • In general, this is a bad idea -

     

    However, if you need to do it, you can just make a thread, mark it with the STA apartment model, and start a new windows forms message loop:

     

    Thread thread = new Thread( () =>
       {
             var yourForm = new SplashForm();
             Application.Run(yourForm);
       });
    thread.ApartmentState = ApartmentState.STA;
    thread.Start();
    



    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Saturday, November 12, 2011 1:19 AM
    Moderator
  • Addition to Jr, you also can use this way:

          Thread thread = new Thread(ShowForm2);
          thread.Start();
    
       void ShowForm2()
       {
          Form2 f2 = new Form2();
          //ShowDialog will create a separated Message loop, UI thread.
          f2.ShowDialog(); 
       }
    
    Have a nice weekend!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us
    Sunday, November 13, 2011 8:54 AM
    Moderator
  • > the main form, and the other one will be for another form that behaves kind of like a splash screen.

       
     
    below is an example of one of the approaches for creating a mainform with splashscreen

     

    using System;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication0
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
    
                var dt = new DataTable();
                dt.Columns.Add("id", typeof(int));
                dt.Columns.Add("text", typeof(string));
    
                var sf = new Splashscreen(dt);
                sf.ShowDialog();
    
                Application.Run(new MainForm(dt));
            }
        }
    
        public partial class MainForm : Form
        {
            public MainForm(DataTable dt)
            {
                this.StartPosition = FormStartPosition.CenterScreen;
                this.Size = new Size(800, 600);
                new DataGridView { Parent = this, Dock = DockStyle.Fill, DataSource = dt };
            }
        }
    
        class Splashscreen : Form
        {
            public Splashscreen(DataTable dt)
            {
                this.StartPosition = FormStartPosition.CenterScreen;
                this.ShowInTaskbar = false;
                this.TopMost = true;
                this.ControlBox = false;
                this.FormBorderStyle = FormBorderStyle.FixedSingle;
    
                var lbl = new Label { Parent = this, Dock = DockStyle.Fill, Text = "Loading" };
                var t = new System.Windows.Forms.Timer { Interval = 100 };
                var i = 0;
                t.Tick += (s, e) =>
                {
                    lbl.Text += ".";
                    dt.Rows.Add(i++, "text" + DateTime.Now.Millisecond);
                    if(i == 20)
                    {
                        this.Close();
                        t.Dispose();
                    }
                };
                t.Start();
            }
        }
    }
    
    

    Sunday, November 13, 2011 9:23 AM
  • Addition to Jr, you also can use this way:

     

          Thread thread = new Thread(ShowForm2);
          thread.Start();
    
       void ShowForm2()
       {
          Form2 f2 = new Form2();
          //ShowDialog will create a separated Message loop, UI thread.
          f2.ShowDialog(); 
       }
    
    Have a nice weekend!

     


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us


    Hi Mike,

    I need this to be not a showdialog() call. both windows should be interactive

    Sunday, November 13, 2011 4:23 PM
  • HI,

    As I metyioned in my previous erply to mike, I need this to be not a showdialog() call. both windows should be interactive. Is there any other way?

    Sunday, November 13, 2011 4:24 PM
  • In general, this is a bad idea -

     

    However, if you need to do it, you can just make a thread, mark it with the STA apartment model, and start a new windows forms message loop:

     

     

    Thread thread = new Thread( () =>
       {
             var yourForm = new SplashForm();
             Application.Run(yourForm);
       });
    thread.ApartmentState = ApartmentState.STA;
    thread.Start();
    


     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".


    Hi reed,

    Does this run from anywehre in my applicatyion? should be in the entry point of the application? as in program.main?

    and is the application.run the call that assigns a message queue to the form?

    Sunday, November 13, 2011 4:26 PM
  • This can be done anywhere - it will just start up a second thread and display the form.  You can set it topmost and have a timer close it if you want it to go away automatically...

     

    The "Application.Run" is what sets up the message pump for that thread, which allows the form to run normally (without being a modal dialog).


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Sunday, November 13, 2011 9:44 PM
    Moderator
  • using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
          BackgroundWorker bgw = new BackgroundWorker();
          bgw.DoWork += bgw_DoWork;
          bgw.RunWorkerAsync();
        }
        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
          Form frm2 = new Form();
          frm2.Text = "Form2";
          frm2.ShowDialog();
        }
      }
    }
    
    

    Sunday, November 13, 2011 9:44 PM
  • kalamantina,
    new Thread(() => { new Form2().ShowDialog(); }).Start();
    new Thread(() => { Application.Run(new Form3()); }).Start();
    

    Both of them is create a new UI thread, a new message loop, so they will not affect the first Form, they will run separately even though you closed the first Form.

    For the ShowDialog behavior you mentioned is in the same thread, the first Form will be operated after you close the second Form. But in this code line, it is just like you boot the Form in a Console application, it helps you create a new message loop in the new UI thread.

    So you can use them everywhere.

    If there's any concern, please feel free to let me know.

    Have a nice weekend!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us
    Monday, November 14, 2011 5:43 AM
    Moderator
  • kalamantina,
    new Thread(() => { new Form2().ShowDialog(); }).Start();
    new Thread(() => { Application.Run(new Form3()); }).Start();
    

    Both of them is create a new UI thread, a new message loop, so they will not affect the first Form, they will run separately even though you closed the first Form.

    For the ShowDialog behavior you mentioned is in the same thread, the first Form will be operated after you close the second Form. But in this code line, it is just like you boot the Form in a Console application, it helps you create a new message loop in the new UI thread.

    So you can use them everywhere.

    If there's any concern, please feel free to let me know.

    Have a nice weekend!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us

    Mike - the second of these is not safe.  You must mark the thread as an STA thread prior to calling Start() if you're using Application.Run.  See my code above for details...

     

     

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Monday, November 14, 2011 6:02 PM
    Moderator
  • Oh, sorry, forgot that! Thanks Jr!

    But it will support much of controls, since they support multi thread operation, except some control has marked as STA, such as WebBrowser, if you use those contorls, then we need the STA attribute to mark our UI thread.

    Have a good day!


    Mike Zhang[MSFT]
    MSDN Community Support | Feedback to us
    Tuesday, November 15, 2011 1:56 AM
    Moderator