3

I want to create a modeless dialog box with below code. However, the form seems not responding after creation. I guess the message loop may be blocked if I create it in this way. Anyone knows how to create it in the correct way?

class Program
{
    static void Main(string[] args)
    {
        Form form = new Form();
        form.Show();
        Console.ReadLine();
    }
}
shi frank
  • 51
  • 1
  • 1
  • 4
  • Surely you meant non-modal? Application.Run() is required, you don't have to call that on your main thread. And you must not, Thread.SetApartmentState() is a rockhard requirement for a UI thread. That makes ShowDialog() a bug, a pretty hard to diagnose one. Use the Thread class. – Hans Passant Jul 24 '16 at 07:58
  • @Hans Passant Yes, you are right. Thanks – shi frank Jul 24 '16 at 14:44

2 Answers2

4

Displaying Modal and Modeless Windows Forms:

To display a form as a modeless dialog box Call the Show method:
The following example shows how to display an About dialog box in modeless format.

// C#
//Display frmAbout as a modeless dialog
Form f= new Form();
f.Show();

To display a form as a modal dialog box Call the ShowDialog method.
The following example shows how to display a dialog box modally.

// C#
//Display frmAbout as a modal dialog
Form frmAbout = new Form();
frmAbout.ShowDialog();

See: Displaying Modal and Modeless Windows Forms


See the following console application code:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

class Test
{
    [STAThread]
    static void Main()
    {
        var f = new Form();
        f.Text = "modeless ";
        f.Show();

        var f2 = new Form() { Text = "modal " };

        Application.Run(f2);
        Console.WriteLine("Bye");

    }
}

you may use another thread, but you must wait for that thread to join or abort it:
like this working sample code:

using System;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleApplication2
{
    static class Test
    {
        [STAThread]
        static void Main()
        {
            var f = new Form { Text = "Modeless Windows Forms" };
            var t = new Thread(() => Application.Run(f));
            t.Start();

            // do some job here then press enter
            Console.WriteLine("Press Enter to Exit");
            var line = Console.ReadLine();
            Console.WriteLine(line);

            //say Hi
            if (t.IsAlive) f.Invoke((Action)(() => f.Text = "Hi"));

            if (!t.IsAlive) return;
            Console.WriteLine("Close The Window");
            // t.Abort();
            t.Join();
        }
    }
}
  • Yes, your code can work. But Application.Run will block. So I have to move it to another thread. – shi frank Jul 24 '16 at 14:36
  • @shi-frank : Yes,you may use another thread, but you must wait for that thread to join or abort it, see last sample code. –  Jul 24 '16 at 16:38
1

Finally, I got it working. In order to unblock my main thread, I have to use a new thread and call Applicatoin.Run to create a message pump for the form. Now both the form and main thread are alive now. Thanks all

class Program
{

    public static void ThreadProc(object arg)
    {
        Form form = arg as Form;
        Application.Run(form);
    }

    [STAThread]
    static void Main(string[] args)
    {
        Form form = new Form() { Text = "test" };

        Thread t = new Thread(ThreadProc);
        t.Start(form);
        string line = Console.ReadLine();
        Console.WriteLine(line);

        form.Close();
    }
}
shi frank
  • 51
  • 1
  • 1
  • 4
  • what happens if you press Enter , before you close that form: you must wait for another thread to join, see my last sample code: **System.InvalidOperationException was unhandled** –  Jul 24 '16 at 15:41
  • I didn't get this error without t.Join(); Actually Application.Run will block until form.Close() is called. So Join before form.Close will be a deadlock. – shi frank Jul 25 '16 at 07:25
  • Um yes, Join() before Close() is wrong. It won't cause deadlock, you can still close the form on GUI but Close() will get called when the form is already closed and possibly disposed. Join() after the Close() on the other hand is ok. – Emperor Orionii Apr 22 '18 at 14:24