从另一个线程(VB.NET)WPF更新控件

时间:2014-09-08 19:50:16

标签: wpf vb.net thread-safety

我是第一次在WPF中创建测试应用程序。我试图更新从另一个线程(非UI线程)在线程UI中创建的列表框。我面临的问题是,无论我在其他线程中找到的所有建议如何,它似乎都不起作用。它对文本框很有用,但不管这个列表框是什么都不行。

我已经尝试创建一个位于窗口本身的实际控件(如果在代码中声明它将是原因)但它不起作用。

如果我尝试使用BeginInvoke,在运行时没有任何反应,但如果我尝试使用Invoke,应用程序就会永远冻结。这是我到目前为止提出的代码。

按钮单击事件:

Dim TableList As New ListBox
 If GetTableList(connection, TableList, DatabaseName, TxtBx_Tasklist) = 0 Then
            MsgBox(TableList.Items.Count)
 Else
 msgbox("FAIL")
 End If

GetTableList功能:

             Dim ThreadResult As Integer
    Dim Thread As New System.Threading.Thread(Sub()
                                                  ThreadResult = _GetTableList(SQLConnection, Listbox, DatabaseName, tasklist)
                                                  'Thread.Sleep(5000)
                                              End Sub)
    Thread.SetApartmentState(ApartmentState.STA)
    Thread.Start()
    Do Until Thread.ThreadState = System.Threading.ThreadState.Stopped
    Loop
    If ThreadResult = 0 Then

        Return 0
    Else
        Return 1
    End If

_GetTableList功能:

       Try

        'Make sure listbox is empty
        Application.Current.Dispatcher.BeginInvoke(New Action(Sub()
                                                                  listbox.Items.Clear()
                                                              End Sub), DispatcherPriority.Background)
        'Declare required components for the SQL operation
        Dim command As New MySqlCommand("SHOW tables;")
        Dim adapter As New MySqlDataAdapter
        Dim data As MySqlDataReader
        Dim TableList As New ListBox

        'Open connection to the server
        SQLConnection.Open()

        'Execute the command
        command.Connection = SQLConnection
        adapter.SelectCommand = command
        data = command.ExecuteReader

        'Update the tasklist control
        Application.Current.Dispatcher.BeginInvoke(New Action(Sub()
                                                                  tasklist.AppendText("Getting table list for database " & DatabaseName & "...")
                                                              End Sub), DispatcherPriority.Background)
        'Process data returned from query and store it in a temporary
        While data.Read
            If data.HasRows Then
                TableList.Items.Add(data(0))
                'MsgBox(data(0) & " " & listbox.Items.Count)
            End If
        End While

        'Update the tablelist
        For Each items In TableList.Items
            listbox.Dispatcher.BeginInvoke(New Action(Sub()
                                                          listbox.Items.Add(items.ToString)
                                                      End Sub))
        Next

        'Closed SQL connections
        SQLConnection.Close()
        SQLConnection.Dispose()

        'Update tasklist control
        tasklist.Dispatcher.BeginInvoke(New Action(Sub()
                                                       tasklist.AppendText("...Done! " & listbox.Items.Count & " tables found." & vbNewLine)
                                                   End Sub), DispatcherPriority.Background)

        'Return 0 to confirm nothing went wrong
        Return 0
    Catch ex As MySqlException
        MsgBox("An error occured while getting the list of tables : " & ex.Number & " , " & ex.Message)
        Return 1
    End Try

使用BeginInvoke更新任务列表控件(这是一个文本框)效果很好,但出于某种原因,更新列表框效果不佳。

我想要更新列表框的任何想法?

1 个答案:

答案 0 :(得分:1)

如果你计划阻塞直到线程完成,你为什么要使用线程?在GUI线程中执行此操作。如果你想在后台运行,请不要阻塞并等待线程完成。

Invoke死锁,因为您传递给Invoke的委托在GUI线程上运行,但GUI线程正在等待后台线程完成,因此不处理消息。