如何使用Timers.Timer从另一个线程安全地调用控件

时间:2018-07-10 20:12:28

标签: vb.net multithreading form-control cross-thread safecontrols

我阅读了各种文章,并做了一个练习项目,但是没有用。 表单上有一个按钮和一个带有默认文本“ Updated 0 times”的文本框。在按钮上单击会启动计时器,并且每次使用更新文本的次数来更新文本。

不会引发跨线程调用的异常,但是在调用文本框时,其.Text =“”,将更新文本,但不更新表单上的文本框。而且InvokeRequired始终为假。

Public Class Form1

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'Here the textBox.Text = "Updated 0 times."
    Dim checking_text As String = Me.TextBox1.Text
    TimerTest.StartTimer()
End Sub


Delegate Sub UpdateTextInvoke(ByVal new_text As String)
Public Sub UpdateText(ByVal new_text As String)
    'Here the textBox.Text = ""
    Dim txtB As TextBox = Me.TextBox1
    'InvokeRequired always = False.
    If txtB.InvokeRequired Then
        Dim invk As New UpdateTextInvoke(AddressOf UpdateText)
        txtB.Invoke(invk, New Object() {new_text})
    Else
        'The value of this text box is updated, but the text on the form TextBox1 never changes
        txtB.Text = new_text
    End If
End Sub
End Class


Public Class TimerTest
Private Shared tmr As New System.Timers.Timer
Private Shared counter As Integer

Public Shared Sub StartTimer()
    tmr.Interval = 5000
    AddHandler tmr.Elapsed, AddressOf UdpateText
    tmr.Enabled = True
End Sub

Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
    counter += 1
    Form1.UpdateText(String.Format("Updated {0} time(s).", counter))
End Sub
End Class

已解决 在类TimerTest中,添加了以下代码“作为Form1 = Form1的私人共享myform” 然后将“ Form1.UpdateText”更改为“ myform.UpdateText”

1 个答案:

答案 0 :(得分:1)

如注释中所示,您正在使用VB.Net的默认表单实例功能。您可以将表单的实例传递给TimerTest类,并用该实例替换对Form1的引用。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim checking_text As String = Me.TextBox1.Text
        TimerTest.StartTimer(Me)
    End Sub
    Public Sub UpdateText(new_text As String)
        If TextBox1.InvokeRequired Then
            Dim invk As New Action(Of String)(AddressOf UpdateText)
        TextBox1.Invoke(invk, {new_text})
    Else
            TextBox1.Text = new_text
        End If
    End Sub
End Class

Public Class TimerTest
    Private Shared tmr As New System.Timers.Timer()
    Private Shared counter As Integer
    Private Shared instance As Form1

    Public Shared Sub StartTimer(formInstance As Form1)
        instance = formInstance
        tmr.Interval = 5000
        AddHandler tmr.Elapsed, AddressOf UdpateText
        tmr.Enabled = True
    End Sub

    Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
        counter += 1
        instance.UpdateText(String.Format("Updated {0} time(s).", counter))
    End Sub
End Class