尽管使用了调用,但UI线程并未通过线程更新进行刷新

时间:2015-12-17 16:35:57

标签: vb.net multithreading winforms user-interface

在表单上,​​我想更新TextBox。更新是从一个线程完成的。 线程就像那样启动:

ComThread = New Thread(AddressOf ComPlcVar.Scan_PLC)
ComThread.IsBackground = True
ComThread.SetApartmentState(ApartmentState.STA)
ComThread.Start()
Console.WriteLine("Do start thread")

更新功能是这样的:

If frmAcc.L_Cas_G.InvokeRequired Then
    Dim d As New L_Cas_Trait_CallBack(AddressOf L_Cas_Trait)
    frmAcc.L_Cas_G.Invoke(d, New Object() {Str})
Else
    frmAcc.L_Cas_G.Text = Str & ControlChars.CrLf & " " & DateTime.Now.ToString("dd/MM/yyy") & " " & DateTime.Now.ToString("HH:mm:ss")
End if

声明函数的委托。

 Public Delegate Sub L_Cas_Trait_CallBack(ByVal str As String)
 Public Sub L_Cas_Trait(Str As String)

但是当我从线程调用更新函数时,我的UI未被更新。

它似乎只是一个用户界面问题,因为当我把写字符放在表格的texchanged方法上时,我得到了一个在控制台上显示正确字符串的事件......

Private Sub L_Cas_G_TextChanged(sender As Object, e As EventArgs) Handles L_Cas_G.TextChanged
    Console.WriteLine(L_Cas_G.Text)
End Sub

有人知道我错过了什么吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

这可能是因为您在页面上的某些位置使用了交叉线程。请尝试使用AppendText。

这样的事情可能是:

Private Delegate Sub AppendTextBoxDelegate(ByVal TB As TextBox, ByVal txt As String)

Private Sub AppendTextBox(ByVal TB As TextBox, ByVal txt As String)
    If TB.InvokeRequired Then
        TB.Invoke(New AppendTextBoxDelegate(AddressOf AppendTextBox), New Object() {TB, txt})
    Else
        TB.AppendText(txt)
    End If
End Sub

并按照以下方式使用:

AppendTextBox(YOURTEXTBOX, ADD YOUR CONTENT HERE)

答案来自:Update Text Box Properly when Cross-threading in Visual Basic (VS 2012 V11)

请查看页面上的完整示例。祝你好运。

答案 1 :(得分:0)

在我的测试中,我发现 invokerequiered 方法永远不会返回true。 我读到,当控件的句柄没有创建但是我用 IsHandleCreated 进行测试时它可能会发生并且看起来没问题。

由于我没有找到解决方案,我决定尝试另一种方法来更新tu UI。

所以我找到了 syncContext.Post 方法,它按预期工作。 我宣布:

Public syncContext As SynchronizationContext

在开始我的线程之前我做了:

syncContext = AsyncOperationManager.SynchronizationContext()

要更新我的文字(或标签):

syncContext.Post(New SendOrPostCallback(AddressOf UpdateStatus), Str_Tmp)

这个电话:

  Private Sub UpdateStatus(ByVal State As Object)
        frmAcc.L_Cas_G.Text = CType(State, String)
  End Sub

现在可行。

感谢大家的帮助。