简体   繁体   中英

When to register a method that will call Form.Invoke to an event?

I get the following exception in a Windows Form application

System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

The method where the exception occurs calls this.Invoke (System.Windows.Forms.Form.Invoke). This method is registered to the event of another class in the constructor, which seems to lead to a race condition and this exception.

public Form1()
{
    InitializeComponent();
    SomeOtherClass.Instance.MyEvent += new SomeDelegate(MyMethod);
}

private void MyMethod()
{
    this.Invoke((MethodInvoker)delegate
    {
        // ... some code ...
    }
}

At which stage of the form lifecycle is the Handle created? In which event of the form would it be safe to register the method to the foreign event?

我想如果您在OnShow事件中注册该方法,您应该是安全的。

Put the InitializeComponent() call back before you register the handler, as suggested by bitxwise

You'll get the same problem when the form is disposed so unregsiter the handler then.

You could do somthing like if(this.IsHandleCreated) in your handler to be safe.

Ok, I now changed it to this:

public Form1(){
    InitializeComponent();
}
protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    SomeOtherClass.Instance.MyEvent += new SomeDelegate(MyMethod);
}
private void MyMethod()
{
    this.Invoke((MethodInvoker)delegate
    {
        // ... some code ...
    }
}

an alternative version would be

public Form1(){
    InitializeComponent();
    SomeOtherClass.Instance.MyEvent += new SomeDelegate(MyMethod);
}
private void MyMethod()
{
    if (this.IsHandleCreated)
    {
        this.Invoke((MethodInvoker)delegate
        {
            // ... some code ...
        }
    }
}

As everyone mentioned already IsHandleCreated is the way to go. Following snippet tells how to do that.

public class TestEvent : Form
{

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        MyMethod();

    }
    private void MyMethod()
    {

        this.Invoke(new Action(() =>
                                   {
                                      //Here goes your code.
                                   }));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM