Multi threading loop freezes ui

2019-08-07 08:51发布

问题:

I'm having trouble with mutli threading programming in my application. Actually, the code looks something like this:

Private Delegate Sub IniciarDiscagemDelegate()

Private Sub CallBack()
    'do some stuff....
    ThreadDiscagem = New Threading.Thread(AddressOf IniciarDiscagem)
    ThreadDiscagem.IsBackground = True
    ThreadDiscagem.Start()
End Sub

Private Sub IniciarDiscagem()
    If Me.InvokeRequired() Then
        Me.BeginInvoke(New IniciarDiscagemDelegate(AddressOf IniciarDiscagem))
        Exit Sub
    End If
    Do While True
       'This boolean is used to control navigation. I set false to it whenever the current entry is closed by the user.
       If Not blnEntryAlreadyOpen Then LookForNewEntries()
    Loop
End Sub

Private Sub LookForNewEntries()
    Dim blnFoundIt As Boolean = False
    Do While Not blnFoundIt
        blnFoundIt = DatabaseMethod()
    Loop
    'Some code that would change UI behavior, show some controls and hide others.
End Sub

Private Sub DataBaseMethod()
    'Code that looks for new entries at the DB
    return true
End Sub

While there are entries available to use, the code runs perfectly. The UI runs fine and the user can navigate. The problem is when there are no entries available, the application stucks at the "LookForNewEntries" loop and freezes the whole UI.

Isn't supposed to not freeze the UI since this loops run directly from a thread not than the main thread?

Could not find any workaround to this problem, can anyone give me a hint?

Thanks!

Best regards.

回答1:

In a matter of fact you are actually running it from the main thread.

This statement is your problem:

If Me.InvokeRequired() Then
    Me.BeginInvoke(New IniciarDiscagemDelegate(AddressOf IniciarDiscagem))
    Exit Sub
End If

You are invoking your method which will make it run on the main thread instead. You are not supposed to use invocation until you are going to modify something on the main thread. So remove that piece of code for now.

For example if you are to change the text of a TextBox you'd need to Invoke.

Example for .NET 4.0 and higher:

If Me.InvokeRequired Then
    Me.BeginInvoke(Sub() TextBox1.Text = "Done")
End If

Example for .NET 3.5 and lower:

If Me.InvokeRequired Then
    Me.BeginInvoke(New IniciarDiscagemDelegate(AddressOf <method to perform changes here>))
End If