繁体   English   中英

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

[英]System.InvalidOperationException: Value Dispose() cannot be called while doing CreateHandle()

在我的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个Label,一个按钮并更改了一些颜色)

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中的原因)。

认为我在这里找到了一个中心: http ://softwareinvent.com/wordpress/?p =10

我今天总是收到一个奇怪的例外:

在执行CreateHandle()时不能调用Value Dispose()

在开始注释大量代码之前,我不知道是什么原因造成的(必须爱蛮力调试)。 一切都归结为非常天真的代码行:

 if (Handle != IntPtr.Zero) 

这行代码将捕获非托管的Windows句柄。 结果,必须手动清理该句柄

看起来完全像我的问题。 也许是一些奇怪的线程问题,在这种情况下,在极少数情况下,会在查询属性HasCaption的同时完全调用HasCaption属性。

首先将其分解,因为现在您无法确定是在对话框中使用using块还是Dispose。

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

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

编辑

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

在My.App.DialogBox.Show()

难以调和

return dialog.ShowDialog();

那么,.Show()或.ShowDialog()是否发生错误?

在运行单元测试时,我也断断续续地遇到了这种异常。 原来这是一个线程问题。 根据时序,另一个线程正试图修改GUI控件,而主测试线程正在拆除并处理包含该控件的表单。

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

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


    `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#必须几乎像这样。

暂无
暂无

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

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