views:

139

answers:

4

how yo show a form which needs to run synchronously. I tried running application.run from a queueworker of a threadpool- but I had some invalid handles sometime. tried using a regular thread but then when main form closes it doesn't close this- and I don't really like the idea of killing the thread on_formclosing. if I use form.show it's fine besides that fact that any showdialog from the main form will block also this. What's the best way to handle this?

+1  A: 

Probably it is the most simple to make the dialog non-modal, i.e. use Show() instead of ShowDialog(). Make the dialog a member of your main form and check in the main form's close event whether the dialog is open and close it if necessary.

0xA3
I *think* that the op was after a form that will open non-modal and will not be blocked by *another* modal form opening from the main form. But I could have read that entirely wrong!
David Hall
@David Hall: After re-reading the question I think you are right.
0xA3
+2  A: 

This is something you really should not fix. Keeping a form enabled while a dialog is displayed is risky. The user could start code from that form that shouldn't run while a dialog is active. Like displaying another dialog.

But you can with a trick and doing it carefully. The ShowDialog() call iterates all open forms and disables them. You could re-enable one by P/Invoking the EnableWindow() API function. The trick is to do so while the dialog is displayed, Control.BeginInvoke() can do this.

This is best explained with an example. It needs three forms and a button on the main form, all with their default names. Form2 is kept non-modal while the dialog is displayed. You may need to move it so it isn't hidden underneath the forms.

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      button1.Click += new EventHandler(button1_Click);
    }
    private Form2 mNonModal;
    void button1_Click(object sender, EventArgs e) {
      this.BeginInvoke(new MethodInvoker(makeNonModal));
      new Form3().ShowDialog(this);
    }
    void makeNonModal() {
      if (mNonModal != null) EnableWindow(mNonModal.Handle, true);
    }
    protected override void OnLoad(EventArgs e) {
      mNonModal = new Form2();
      mNonModal.FormClosed += (s, ea) => mNonModal = null;
      mNonModal.Show();
    }
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern void EnableWindow(IntPtr hWnd, bool enable);
  }
Hans Passant
How about the other way around, making all dialogs non-modal, but make pseudo-modal dialogs: set the dialog's owner to the main form and disable the main form while the dialog is displayed? Leaves me with a better feeling, because a modal dialog "starts its own message loop, taking temporary control of the message queue for the entire application" (see http://msdn.microsoft.com/en-us/library/ms644994%28VS.85%29.aspx#modal_boxes).
0xA3
And by the way, the question reminds me of that cheeseburger, Raymond is talking about: http://blogs.msdn.com/oldnewthing/archive/2007/07/12/3821577.aspx .... mmmmmh... cheeese...
0xA3
Well, as long as the answer doesn't remind you about anything. Admittedly, it is hard to put it in a food group.
Hans Passant
+1  A: 

You can just set IsBackground property of you thread to true, then you background thread will close when all foreground threads closed. You can read about background and foreground threads on msdn.

Andrew
A: 

Try to use Show() instead of ShowDialog(). And also, create the object of your form class, for example MyForm^ theForm = gcnew MyForm();

manuel