System.InvalidOperationException:执行CreateHandle()时无法调用值Dispose()

时间:2010-09-22 10:13:41

标签: c# .net winforms dispose

在我的Windows窗体应用程序中,客户端有时会报告一个奇怪的异常:

System.InvalidOperationException: Value Dispose() cannot be called while doing CreateHandle()
   at System.Windows.Forms.Control.Dispose(Boolean disposing)
   at System.Windows.Forms.ContainerControl.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Dispose()
   at MyCompany.SomeApp.DialogBox.Show(string caption, string message)
   at MyCompany.SomeApp.MainForm.Button1_Click(Object sender, MouseEventArgs e)

导致此错误的代码如下所示:

namespace MyCompany.SomeApp
{
    public class DialogBox : CustomForm
    {
        public static DialogResult Show(string caption, string message)
        {
            using (DialogBox dialog = new DialogBox())
            {
                dialog.Text = caption;
                dialog.lblMessage.Text = message;
                return dialog.ShowDialog();
            }
        }
    }
 }

DialogBox基本上是一个继承自Windows.Forms.Form的类,并做了一些设计更改,没什么特别的。例外情况发生在

return dialog.ShowDialog();

而不是像我期望的那样using块的末尾。看起来在某种程度上,在ShowDialog()方法中,在创建表单句柄之前,调用Dispose()方法。 但我的DialogBox既没有调用Dispose()本身也没有吞下其他异常,它只在OnPaint()事件中做了一些绘画。

有没有人有一些线索如何摆脱这种异常?

更新

这是我的CustomForm类中唯一的代码(除了Windows窗体设计器中的更改模式(添加了2个标签,一个按钮并更改了一些颜色)

Public Class CustomForm
    Inherits System.Windows.Forms.Form

    <DebuggerStepThrough()> _
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        Static pen1 As New Pen(Color.FromArgb(39, 46, 54), 21)
        Static pen2 As New Pen(Color.FromArgb(44, 51, 59), 1)
        Static pen3 As New Pen(Color.FromArgb(93, 99, 99), 1)
        Static pen4 As New Pen(Color.FromArgb(119, 124, 127), 1)
        Static pen5 As New Pen(Color.FromArgb(148, 157, 156), 1)
        Static pen6 As New Pen(Color.FromArgb(175, 185, 186), 1)

        With e.Graphics
            .DrawRectangle(Pens.Black, 0, 0, (Me.Width - 1), (Me.Height - 1))
            .DrawLine(pen1, 1, 11, Me.Width - 1, 11)
            .DrawLine(pen2, 1, 22, Me.Width - 2, 22)
            .DrawLine(pen3, 1, 23, Me.Width - 2, 23)
            .DrawLine(pen4, 1, 24, Me.Width - 2, 24)
            .DrawLine(pen5, 1, 25, Me.Width - 2, 25)
            .DrawLine(pen6, 1, 26, Me.Width - 2, 26)
        End With
    End Sub

    Private Const GWL_STYLE As Integer = (-16)
    Private Const WS_CAPTION As Integer = &HC00000
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
             (ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
    Public ReadOnly Property HasCaption() As Boolean
        Get
            return (GetWindowLong(Me.Handle, GWL_STYLE) And WS_CAPTION) = WS_CAPTION
        End Get
    End Property

End Class

更新:我稍微更改了代码,因为它具有误导性 在堆栈跟踪中,您可以看到调用了My.App.DialogBox.Show(...)。这是一个包含using块的静态方法 DialogBox nore CustomForm都没有覆盖Form的ShowDialog()方法(这就是为什么它没有显示在stacktrace中。

4 个答案:

答案 0 :(得分:3)

想想我在这里发现了一个:http://softwareinvent.com/wordpress/?p=10

  

我今天得到一个奇怪的例外:

     

值Dispose()无法调用   做CreateHandle()

     

我无法弄清楚究竟是什么造成的   直到我开始评论   大量的代码(得到爱   强制调试)。一切都降下来了   一个非常无辜的线条   代码:

if (Handle != IntPtr.Zero)
     

这行代码抓取了一个不受管理的代码   Windows句柄。结果,那   手柄必须手动清理

看起来完全像我的问题。也许是一些令人讨厌的线程问题,在极少数情况下,HasCaption属性与查询属性HasCaption的同时被调用。

答案 1 :(得分:1)

首先分解它,因为现在你无法判断它是否是使用块或对话框内的Dispose。

以下内容将在调试器中提供更多信息:

using (DialogBox dialog = new DialogBox())
{
    dialog.Text = caption;
    var r = dialog.ShowDialog();
    return r;
}

修改

我在错误消息中找到了这一行

  

at My.App.DialogBox.Show()

难以与

协调
return dialog.ShowDialog();

那么,.Show()或.ShowDialog()会发生错误吗?

答案 2 :(得分:1)

我在运行单元测试时也一直关闭这个例外。事实证明这是一个线程问题。根据时间安排,另一个线程试图在主测试线程被拆除并处理包含控件的表单时修改GUI控件。

我退出单元测试以等待所有预期的GUI更新(即使这不是正在测试的内容),然后退出并解决问题。

答案 3 :(得分:0)

这是一个很老的问题。但如果有人对此感兴趣,这就是我的解决方案。


    `Timer tmr = new Timer();
    tmr.Interval = 1000;
    tmr.Tick += tmrTick;
    tmr.Start();
    void tmrTick(Object sender, EventArgs e){
        Timer tmr = sender as Timer;
        tmr.Stop();
        Form.Close(); //Form is form which wants to close by instance name. for example: this.Close()
    }`

也许有一些错误的语法导致我自己将Vb转换为c#。非常遗憾。 但它必须与c#几乎相同。