Frage

So, i've been searching trough similar topics on stackoverflow and on other internet forums and knowledge bases but so far i had no luck trying to solve this problem i've been struggling for a whole week. Here is the code:

    private void matrículasToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Form1 form1 = new Form1();
        form1.Show();
        form1.MdiParent = this; // this == the main form of the aplication, wich has IsMdiParent property set to true.
    }

If i take out the "form1.MdiParent = this", the shown event of form1 will fire normally, executing all of its handler's content, but if i let it there, shown event of form1 will not fire (i did set breakpoits, none of them triggered).

Curiously, if i use the Load event instead of Shown, everything works fine, but i'm a bit afraid if swapping Shown for Load would break something :(.

War es hilfreich?

Lösung

Try this code

 Form1 form1 = new Form1();
 //Subscribe event here
 form1.MdiParent = this;
 form1.Show();

This works for me

I don't know why your code doesn't work, I'll get back once I get the answer.

Edit: I have got the answer now.

ISynchronizationInvoke's members (Invoke and BeginInvoke) are implemented by Control class as follows.

  1. Gets context of Thread which created the window.
  2. Generate a new window messageId using RegisterWindowMessage
  3. Encapsulate the delegate we passed as a parameter in ThreadMethodEntry add it into control's internal Queue
  4. Posts the message to thread's queue with messageId returned by RegisterWindowMessage using PostMessage
  5. Handles WndProc listens for messageId then De-queues the ThreadMethodEntry and invokes the delegate.

What goes wrong here?

Form1 form1 = new Form1(); form1.Show(); form1.MdiParent = this;

Form.Show somehow results in a call to OnLoad method, that is where OnShown is called Asynchronously using BeginInvoke

if (base.IsHandleCreated)
{
    base.BeginInvoke(new MethodInvoker(this.CallShownEvent));//reflected code
}

So before the posted WindowMessage receives you set form1.MdiParent = this; which in turn forces the control to Destroy it's handle and ReCreate new handle.

DestroyHandle method swallows the posted message by getting it using PeekMessage function, and then enumerates all elements in Queue and sets its state as completed without invoking the delegate but marking it to throw ObjectDisposedException.

Form1 form1 = new Form1();
form1.Show();
Action del = () =>
{
    Console.WriteLine("This will never be called");//our custom delegates too fails to be invoked
};
var res = form1.BeginInvoke(del);
//after some more code
form1.EndInvoke(res);//throws `ObjectDisposedException` which was marked previously
form1.MdiParent = this;

throwing ObjectDisposedException("Control") is actually misleading isn't it?

Note: You can fix this easily using Application.DoEvents(); before form1.MdiParent = this; since DoEvents process all the pending messages immediately.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top