views:

101

answers:

1

In my windows forms app clients sometimes report a strange exception:

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)

The code that causes this error looks like this:

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 is basically a class that inherits from Windows.Forms.Form and does some design changes, nothing special. The excepions happens at

return dialog.ShowDialog();

and not at the end of the using block as I would expect. It looks like somehow, within the ShowDialog() method and before the form's handle is created, the Dispose() method is called. But my DialogBox neither calls Dispose() itself nor swallows other exceptions, it only does some painting in the OnPaint() event.

Does anybody have some clues how to get rid of this exception?

Update:

Here is the only code in my CustomForm class (besides changes mode in the windows forms designer (added 2 Labels, a button and changed some colors)

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

Update: I changed the code a little bit because it was misleading.
In the stacktrace you can see that My.App.DialogBox.Show(...) is called. Which is a static method that contains the using block.
Neither DialogBox nore CustomForm override the ShowDialog() method of Form (which is why it is not shown in the stacktrace.

A: 

Think I found a clou here: http://softwareinvent.com/wordpress/?p=10

I kept getting an odd exception today:

Value Dispose() cannot be called while doing CreateHandle()

I couldn’t figure out what was causing it until I started commenting out large swaths of code (gotta love brute force debugging ). It all came down to a very innocent looking line of code:

if (Handle != IntPtr.Zero)

This line of code grabs an unmanaged Windows handle. As a result, that handle must be manually cleaned up

Looks exactly like my problem. Maybe some weired threading issue in which, in rare conditions the HasCaption property is called exactly at the same time as the property HasCaption gets queried.

SchlaWiener