简体   繁体   English

何时注册将Form.Invoke调用到事件的方法?

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

I get the following exception in a Windows Form application 我在Windows窗体应用程序中得到以下异常

System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created. System.InvalidOperationException:在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。

The method where the exception occurs calls this.Invoke (System.Windows.Forms.Form.Invoke). 发生异常的方法调用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? 表单生命周期的哪个阶段是Handle创建的? 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 按照bitxwise的建议,在注册处理程序之前调用InitializeComponent()

You'll get the same problem when the form is disposed so unregsiter the handler then. 当表单被处理时你会遇到同样的问题,因此处理器处于ungs。

You could do somthing like if(this.IsHandleCreated) in your handler to be safe. 你可以在你的处理程序中做if(this.IsHandleCreated)这样的事情是安全的。

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. IsHandleCreated已经IsHandleCreated之路。 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.
                                   }));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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