当前位置:编程学习 > C#/ASP.NET >>

使用 System.Timers.Timer 更新TrackBar1 UI时发生跨线程的错误

我的问题如标题  小弟在设计用System.Timers.Timer  这个定时器

去累加 TrackBar1的位置 结果却跑出跨线程的错误

我上网查了些资讯 好似说要用委派及将更新的form类别丢进去这些信息

我参考了网络上的信息 写了些代码 但还是出现跨线程错误

应该是我的委派的代码好像写得有点问题 请各位大大指导一下

这边该怎么写才对


Private newtime As New System.Timers.Timer
    Private Sub Button3_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        'If Timer4.Enabled = False Then
        '    Me.Timer4.Start()
        'End If
        '==============System.Timers.Timer
        AddHandler newtime.Elapsed, AddressOf Timers_Timer_Elapsed
        newtime.Interval = 20
        newtime.Start()
        '==============
    End Sub

    Sub Timers_Timer_Elapsed()
        Me.newtime.SynchronizingObject = Me
        Me.BeginInvoke(New UpdateControl(AddressOf _mUpdateControl), New Object() {TrackBar1})

        If Not TrackBar1.Value = TrackBar1.Maximum Then
            'Me.TrackBar1.Value += 1

            Me.BeginInvoke(New UpdateControl(AddressOf _mUpdateControl), New Object() {TrackBar1})
    
        Else
            TrackBar1.Value = 0
            newtime.Stop()
        End If

    End Sub

    Private Delegate Sub UpdateControl(ByVal Ctrl As TrackBar)
    Private _objLock As New Object()
    Private Sub _mUpdateControl(ByVal Ctrl As TrackBar)
        SyncLock Me._objLock
            If TypeOf Ctrl Is TrackBar Then
                Ctrl.Value += 1
            End If
        End SyncLock
    End Sub


--------------------编程问答-------------------- TrackBar1.Value = TrackBar1.Maximum

所有操作界面的语句,无论读写,都要放在委托中。

另外,用Invoke而不是BeginInvoke,因为你这里需要同步处理。 --------------------编程问答--------------------
    Private newtime As New System.Timers.Timer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        AddHandler newtime.Elapsed, AddressOf Timers_Timer_Elapsed
        newtime.Interval = 20
        newtime.Start()
    End Sub

    Sub Timers_Timer_Elapsed()
        Me.BeginInvoke(Sub()
                           If Not TrackBar1.Value = TrackBar1.Maximum Then
                               TrackBar1.Value += 1
                           Else
                               TrackBar1.Value = 0
                               newtime.Stop()
                           End If
                       End Sub)
    End Sub
--------------------编程问答-------------------- 当然,你的这段程序可以这样写
    Private newtime As New System.Timers.Timer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Me.newtime.SynchronizingObject = Me
        AddHandler newtime.Elapsed, AddressOf Timers_Timer_Elapsed
        newtime.Interval = 20
        newtime.Start()
    End Sub

    Sub Timers_Timer_Elapsed()
        If Not TrackBar1.Value = TrackBar1.Maximum Then
            TrackBar1.Value += 1
        Else
            TrackBar1.Value = 0
            newtime.Stop()
        End If
    End Sub


这是因为你的 Elapsed 中的处理,其实都没有什么“后台处理意味”,都是简单地更新界面上的控件,所以他们需要全都放在主线程执行。因此这里怎么写都可以。

你的这个例子并不能显示线程编程的好处,只是说明了线程中操作控件必须额外多写一行委托而已。 --------------------编程问答-------------------- 我这边的需求是这样 我要设计一个以1ms为单位的累加定时器 去比对要触发另一个动作的时间去触发动作 但我不希望当触发动作时累加定时器就因为要去跑触发动作的程序 然后就不继续累加计时了  所以这里才选择设计成一个独立线程的timer

再来听到板主大大的回文再加上sp1234 大大的回文 我整理一下思绪 我这里需要的功能 似乎是需要能同时动作的 也就是说累加定时器照常在跑并移动TrackBar1 然后另一个timer则是不断每隔1ms就去比对要触发动作的时间点 

所以我应该是要用Invoke 做同步处理
 

Me.Invoke(Sub()
                      If Not TrackBar1.Value = TrackBar1.Maximum Then
                          TrackBar1.Value += 1
                      Else
                          TrackBar1.Value = 0
                          newtime.Stop()
                      End If
                  End Sub)
补充:.NET技术 ,  VB.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,