2

I'm having a strange hang issue with my VB.Net application. When the user clicks an update button, the below is run as a thread to do some long calculations on the data. It disables the control, shows a 'Working...' text box, does the work, re-enables the controls and gets rid of the 'Working...' text box. Occasionaly (I've never reproduced while debugging), the users window freezes and hangs. When it happens CPU usage is 0 so its done with the calculations, but the controls still show as disabled and the 'Working...' text box is still visible, although the window is completely stuck and will not update. This will stay this way indefinitely (users have tried waiting up to 30 minutes). Oddly, I can 'unstick' the window only by clicking the minimize/restore buttons from the right click menu of the window on the task bar. After a short delay the window springs back to life. The minimize/restore of the window itself don't seem to have an effect.

So my question, what am I doing wrong in my below thread?

Dim Thread As New Threading.Thread(AddressOf SubDoPriceUpdateThread)
Thread.Start()

Thread:

    Private Sub SubDoPriceUpdateThread()

            Dim Loading As New TextBox
            Try
                CntQuotePriceSummary1.Invoke(New Action(Of Control)(AddressOf CntQuotePriceSummary1.Controls.Add), Loading)
                CntQuotePriceSummary1.Invoke(New Action(Sub() CntQuotePriceSummary1.Enabled = False))

                Loading.Invoke(New Action(AddressOf Loading.BringToFront))
                Loading.Invoke(New Action(Sub() Loading.Text = "Working..."))

                '***Long running calculations***

                Invoke(New Action(AddressOf FillForm))

            Finally
                CntQuotePriceSummary1.Invoke(New Action(Of Control)(AddressOf CntQuotePriceSummary1.Controls.Remove), Loading)
                CntQuotePriceSummary1.Invoke(New Action(Sub() CntQuotePriceSummary1.Enabled = True))
                Loading.Invoke(New Action(AddressOf Loading.Dispose))
            End Try

    End Sub
Kratz
  • 4,280
  • 3
  • 32
  • 55
  • If Loading is the name of your form then its Invoke() method does not actually invoke to the UI thread. Violating threading requirements and apt to cause deadlock. See http://stackoverflow.com/a/14287947/17034 – Hans Passant Jan 16 '13 at 16:53
  • @HansPassant, Loading is a text box, created at the top of the function, just to show a simple "Working" text on top of the control that shows the totals the user is refreshing. Its added to the `CntQuotePriceSummary` at the top and then removed and disposed of in the `Finally` block. – Kratz Jan 16 '13 at 17:42
  • `As New TextBox` can never work. You must use an existing control that was created on the UI thread. That is the only way it can figure out which thread needs to be invoked to. If your snippet is accurate then Me.Invoke() will work. – Hans Passant Jan 16 '13 at 18:58

1 Answers1

0

Per Hans's comments, its clear that the Loading text box is not created on the UI thread and that's what would've cause the deadlock issue. I've rewritten the code.

     Private Sub SubDoPriceUpdateThread()

            Dim Loading As TextBox
            Invoke(Sub() Loading = New TextBox)

            Try
               Invoke(Sub()
                           CntQuotePriceSummary1.Controls.Add(Loading)
                           CntQuotePriceSummary1.Enabled = False
                           Loading.BringToFront()
                           Loading.Text = "Working..."
                       End Sub)

               '***Long running calculations***

                Invoke(Sub() FillForm())

            Finally
                Invoke(Sub()
                           CntQuotePriceSummary1.Controls.Remove(Loading)
                           CntQuotePriceSummary1.Enabled = True
                           Loading.Hide()
                           Loading.Dispose()
                       End Sub)
            End Try

    End Sub
Kratz
  • 4,280
  • 3
  • 32
  • 55