Search code examples
windowsvb.netmultithreadingdisposeinvoke

Window occasionally hangs/freezes while running thread


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

Solution

  • 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