I am trying to instantiate a Form directly from a Console App.
For some weird reason, when I call Form1.Show() the newly created Form doesn’t draw all its controls and Freezes (HourGlass icon). However, when I call ShowDialog(), everything goes fine, except that I need to go back to Console but I can’t, so it is not an option…
What should I do to make my Form display correctly ? Am I missing something here ?
OrderControlForm OrderControlBox = new OrderControlForm();
OrderControlBox.BuyEvent += new OrderControl.BuyDelegate(doBuy);
OrderControlBox.SellEvent += new OrderControl.SellDelegate(doSell);
OrderControlBox.Show();
The above code is called in response to a command entered by the Console user.
EDIT :
Here is the working code :
Thread mThread = new Thread(delegate()
{
StratControlBox = new StratControl(StratIDs);
StratControlBox.ShowDialog();
});
mThread.SetApartmentState(ApartmentState.STA);
mThread.Start();
I still don’t see why I had to call ShowDialog() rather than Show().
When I use the latter the Form just “disappears” instantly after paint.
The reason is because
ShowDialogperforms its own message loop, whereasShowdoes not. Instead of callingShow, you would need to callApplication.Run, which performs a message loop. However, since it synchronously loops, processing incoming window messages until the form is closed, it will be effectively no different than callingShowDialog.Therefore, if you want to show the form asynchronously, you would need to do so from another thread. However, just to be safe, make sure the new thread uses apartment threading by calling
newThread.SetApartmentState(ApartmentState.STA);.Also, I’d recommend only showing one main form from one UI thread. If that main form shows other forms from its own thread, that’s fine, but, if you start trying to show multiple forms, each from their own thread, it can cause problems.
Regarding Your Update
The reason that calling
Showfrom the thread does not work is two-fold. First, it is synchronous, so it does not return until the form is closed. That is important because as soon as execution leaves your anonymous method, the thread will terminate. So, when you callShow, it immediately returns, then leaves your method thereby terminating the thread.Second, even if the form did stay open, it would be unresponsive, just as before, for all the same reasons. WinForms require a message loop that keeps looking for new incoming window messasges and processing them. The message loop calls a method called
WndProc. Without a message loop calling theWndProcmethod to process the incoming window messages, the form will be totally unresponsive to users. For instance, when the mouse driver notifies windows that the user has pressed the mouse button, windows will then posts aWM_MOUSEDOWNmessage to your application’s message queue. If you don’t have code somewhere that is constantly looping looking to see if there are any messages in the queue and acting upon them, you’ll never get the mouse down event.As I mentioned above, the
ShowDialogmethod performs its own message loop, so it works, butShowdoes not.Showassumes that it is being called by an already running message loop. If for some reason you don’t want to callShowDialog, you can callApplication.Run(StratControlBox), instead. TheRunmethod will show the form for you and then stay in a message loop until the form is closed. Therefore, it is a synchronous call, just likeShowDialog, so your thread won’t terminate until the form is closed.