title: Using a .NET class library to display a form in response to COM Event freezes the form
body: <p>I'm creating a .NET component that I want to use to simplify working with an application that supports a COM Automation interface.  One of the features of the component is that it will display dialogs to collect information from the user.  However, in the workflow that I need to use, the dialog is partially displayed and then it freezes.</p>
  
  <p>I've created a simplified version of what I'm doing using Excel. I'm actually using another application with a COM Automation interface but the problem is a general problem and is reproducible using Excel, which most people should have. Here's a brief description of the various pieces. I'm writing this in Visual Basic but assume the same problem will occurr with C# although I haven't tested that.</p>
  
  <p><strong>.NET Class Library project "MyCmd"</strong></p>
  
  <p><strong>Class MyDef</strong></p>
  
  <p>When an instance of the MyDef class is created, it gets and saves the currently active Excel sheet.  It also listens to the SelectionChange event of the Excel Sheet object.  In response to the SelectionChange event, it creates an instance of the "MyCmd" class (described below) and fires a custom CommandCreated event, passing the created MyCmd object.</p>
  
  <p>It also supports a public method called ForceEvent which does the same thing as the SelectionChange event. This is used to test the functionality using a different code path.</p>
  
  <pre><code>Imports Microsoft.Office.Interop.Excel
  
  Public Class MyDef
      Private WithEvents _sheet As Microsoft.Office.Interop.Excel.Worksheet
      Public Event CommandCreated(ByVal command As MyCmd)
  
      Public Sub New()
          _sheet = g_app.ActiveSheet
      End Sub
  
      Public Sub ForceEvent()
          Dim cmd As New MyCmd()
          RaiseEvent CommandCreated(cmd)
      End Sub
  
      Private Sub _sheet_SelectionChange(Target As Range) Handles _sheet.SelectionChange
          Me.ForceEvent()
      End Sub
  End Class
  </code></pre>
  
  <p><strong>Class MyCmd</strong></p>
  
  <p>A class that contains a single method that creates a new instance of a dialog and displays it.</p>
  
  <pre><code>Public Class MyCmd
      Private _form As Form = Nothing
  
      Public Sub ShowDialog()
          If _form Is Nothing Then
              _form = New CommandDialog
          End If
  
          _form.Visible = True
      End Sub
  End Class
  </code></pre>
  
  <p>The dialog I'm testing with is a form (named "CommandDialog") with a couple of buttons and no code behind them.  I'm just testing to see if the form is displayed as expected.</p>
  
  <p><strong>Globals Module</strong></p>
  
  <p>I'm also using the code below to connect to Excel and get the Excel Application object.  It works as expected.</p>
  
  <pre><code>Public Module Globals
      Private _app As Microsoft.Office.Interop.Excel.Application = Nothing
  
      Public Function g_app() As Object
          If Not _app Is Nothing Then
              Return _app
          Else
              Try
                  _app = GetObject(, "Excel.Application")
              Catch ex As Exception
                  MsgBox("Excel must be running")
                  Return Nothing
              End Try
              Return _app
          End If
      End Function
  End Module
  </code></pre>
  
  <p><strong>.NET Class Library project "MyCmd"</strong></p>
  
  <p>I also have another project called "CommandFramework" that is using the MyCmd class library.  This second project is a Windows Form App that contains two buttons and an event handler for the CommandCreated event supported by MyDef.  The entire code is below.</p>
  
  <p>When the first button is clicked, it creates an instance of the MyDef class, which because of the WithEvent declaration, also sets up an event handler for the CommandCreated event.  Clicking the second button calls the ForceEvent method which results in firing the CommandCreated event and displays the dialog. I can also click in a cell in the active Excel sheet and that causes the SelectionChange event to be fired and results in the ForceEvent method to be called.  However, in this case, the dialog is only partially displayed and is frozen.  The code flow is identical except for the trigger which is either clicking the second button or receiving the Excel SelectionChange event. The second case causes the freeze.</p>
  
  <pre><code>Public Class CommandFramework
      Private WithEvents _cmdDef As MyCommand.MyDef = Nothing
  
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
          _cmdDef = New MyCommand.MyDef
      End Sub
  
      Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
          _cmdDef.ForceEvent()
      End Sub
  
      Private Sub cmdDef_CommandCreated(command As MyCommand.MyCmd) Handles _cmdDef.CommandCreated
          command.ShowDialog()
      End Sub
  End Class
  </code></pre>
  
  <p>Does anyone have any ideas what the cause of the problem is and what a solution might be?  My guess is it's some kind of threading issue and there's a deadlock but I don't know enough about that area to even begin diagnosing or trying something else.</p>