为什么thread.join会冻结vb.net中的用户界面

时间:2017-05-10 07:11:26

标签: .net vb.net multithreading

我正在尝试多线程。创建线程后,我的UI似乎冻结,因为我正在尝试加入创建的线程。如果我不加入我的线程,那么一切似乎都有效。

以下是我的代码。

Public Class FrmGraphWithThreads

    Dim t As Thread
    Dim tlist As List(Of Thread)

    Private Sub FrmGraphWithThreads_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        UpdateTextDelegate = New UpdateTextSub(AddressOf UpdateText)
        tlist = New List(Of Thread)
    End Sub


#Region " Delegate and Delegate SUB to update Text Box "

    Private Delegate Sub UpdateTextSub(ByRef txtbx As TextBox, ByVal val As String)
    Private UpdateTextDelegate As UpdateTextSub
    Private Sub UpdateText(ByRef txtbx As TextBox, ByVal val As String)
        txtbx.Text = val
    End Sub

#End Region

    Private Sub CalculateTable(ByVal itm As Object)
        Dim _int = CInt(itm)
        Dim i As Integer

        If _int > 0 Then
            Select Case _int
                Case 1
                    For i = 1 To 10
                        Dim _val = _int * i
                        txtBx1.Invoke(UpdateTextDelegate, New Object() {txtBx1, _val.ToString})
                        Thread.Sleep(1000)
                    Next
                Case 2
                    For i = 1 To 10
                        Dim _val = _int * i
                        txtBx2.Invoke(UpdateTextDelegate, New Object() {txtBx2, _val.ToString})
                        Thread.Sleep(1000)
                    Next
            End Select
        End If
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim i As Integer

        For i = 1 To 2
            t = New Thread(AddressOf CalculateTable)
            t.Name = i.ToString
            t.Start(i)
            tlist.Add(t)
            Thread.Sleep(10)
        Next

        For Each itm As Thread In tlist
            itm.Join()'This causes freezing. Without join everything is working.
        Next
    End Sub
End Class

任何想法都会有很大的帮助。

1 个答案:

答案 0 :(得分:1)

您正在从UI线程调用Thread.Join。这意味着UI线程被阻塞,直到所有其他线程完成。这是一个坏主意一般,因为这意味着您的UI被阻止,而所有其他线程都可以工作。

在这种情况下,它比一个坏主意更糟糕 - 它会死锁,因为你从其他线程调用Control.Invoke,例如:

txtBx2.Invoke(UpdateTextDelegate, New Object() {txtBx2, _val.ToString})

Control.Invoke阻止调用线程,直到UI执行了给定的委托。所以你有后台线程被阻塞,直到UI线程完成工作,并且UI线程被阻塞,直到后台线程完成。死锁。

您几乎肯定会考虑使用async / await和tasks来代替此手动线程。它会让你的生活更轻松。