Windows窗体-使用BeginInvoke如果form_load事件失败

本文关键字:load 事件 失败 form 如果 窗体 使用 BeginInvoke Windows | 更新日期: 2023-09-27 18:06:03

今天我注意到我的代码中的一个错误,我以为我已经处理了一段时间了。我正在开发Windows Forms应用程序,并且经常使用form_load事件。为了处理Form_load事件中出现问题并抛出异常的情况,我使用以下代码:

catch (Exception ex)
{
    LogErrorAndShowMessage(ex, Resources.ERROR_LOAD);
    //Otherwise Error : "Cannot call Close() while doing CreateHandle()".
    this.BeginInvoke(new InvokeDelegate(CloseTheForm));
    LoadForm<Materials>(closeAlreadyOpened : false);
}

我是这样声明委托和方法的

public delegate void InvokeDelegate();//used if form load fails
private void CloseTheForm()
{
    this.Close();
}

从今天起就一直很好。发生了什么-在Form_load事件中,我为我的组合框设置了DataSource,并且碰巧从SetDataSource方法抛出了一个错误,最终导致了我在使用BeginInvoke - Cannot call Close() while doing CreateHandle()之前得到的完全相同的错误。

这是异常行为,如果异常是从其他地方抛出的代码仍然工作良好,只有当它在设置数据源期间,我得到了错误。

有什么建议可能导致这种异常行为,我如何修复它?

p。S

下面是我创建新表单的方法:
protected void LoadForm<T>(ToolStripButton/*ToolStripDropDownButton*/ formButton, 
                           string buttonText, 
                           long? loadEntityId = null, 
                           bool closeAlreadyOpened = true) where T : BaseForm
{
    MainForm parentFrm = GetParentForm();
    if (parentFrm != null)
    {
        if (formButton != null)
        {
            parentFrm.SetForeColor(formButton);
        }
        T openForm = SingletonFormProvider.GetInstance<T>(parentFrm, 
                                                          closeAlreadyOpened);
        openForm.LoadEntityId = loadEntityId;
        openForm.MdiParent = parentFrm;
        openForm.Dock = DockStyle.Fill;
        openForm.Show();
        openForm.Activate();
    }
    else
    {
        MessageBox.Show("Parent form not found!", "Error", 
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

也许作为Hans Passant提供我应该把try-catch围绕openForm.Show()来处理这个问题?

Windows窗体-使用BeginInvoke如果form_load事件失败

Load事件就像这样麻烦。它通常在调用表单的Show()方法时触发。但是,如果表单构造函数中的初始化代码需要创建本机窗口,那么它可以提前触发。相当不健康,因为form对象还没有完全初始化。你总是可以通过在Load事件处理程序中设置断点并查看调试器的调用堆栈窗口来找出是什么代码做了这个。

一般来说,您应该避免Load事件,只有在需要知道窗口的实际大小的极少数情况下才需要它。其他所有内容都属于构造函数,就像普通的。net类一样。您需要做一些关于捕获和记录异常的事情,这最好使用类工厂来完成。样板工厂可以像这样:

    public static Form1 CreateInstance() {
        try {
            var frm = new Form1();
            frm.Show();
            return frm;
        }
        catch (Exception ex) {
            LogErrorAndShowMessage(ex);
            return null;
        }
    }