当前位置: 代码迷 >> VB Dotnet >> 事件触发的响应与多线程有关问题。新人诚心
  详细解决方案

事件触发的响应与多线程有关问题。新人诚心

热度:123   发布时间:2016-04-25 02:06:12.0
事件触发的响应与多线程问题。新人诚心求助
本帖最后由 mavswr 于 2015-01-01 22:06:33 编辑
作为一个非专业人员,开发一个测试系统时遇到了问题,请大家赐教!
本人是刚开始用vb.net,被搞的焦头烂额。请大家一定帮忙,回复请尽量清楚,因为我是菜鸟一个。

我在写一个自动数据采集数据,用的是NI的visa库。
具体工作流程如下:多数时间里,我每隔100ms读取设备1的数据并画图,这部分我是用timer实现的。

同时设备2会会每间隔一段时间发出一个触发信号,我希望捕捉这个触发信号并触发一个事件,在这个时间中读设备2的一些状态字,来确定是否继续读设备1。当遇到设备2产生特殊事件时,要及时停止程序。  现在问题是,设备2运转慢时,即设备2的触发信号间隔比较长时,我可以捕捉到设备2 的停止状态信号,但是,当设备2运转快时,好像就没办法捕捉到停止信号了。以下是代码。请帮我看看,该如何改进?

主程序中:
ZTsession是一个ni Visa 的设备对象。。。。

 AddHandler ZTSession.ServiceRequest, AddressOf OnServiceRequest                          ‘安装事件触发
   ZTSession.EnableEvent(MessageBasedSessionEventType.ServiceRequest, EventMechanism.Handler)   ’触发使能
 ScanStopFlag = 0
 Timer1.Start()                                        ‘设备1的读数与绘图程序使能


触发事件程序OnServiceRequest 如下:

 Private Sub OnServiceRequest(ByVal sender As Object, ByVal e As MessageBasedSessionEventArgs)
           Dim ZTRSQByte As Byte
        Dim responsstring As String
    '当设备2 有事件触发响应时,首先读取设备2 的状态字,并进行判断,遇到某些状态时,执行对应的处理,
'其中最主要的处理是停止Timer1的tick
'并使用全局变量ScanStopFlag 来记录是何种情况。
''但貌似当触发很快’‘时,timer会捕捉”停止状态“的变化,或者说不响应Call Clearstop_Rastscan()!
'但是,如果在每个Call Clearstop_Rastscan()前下断点,就能保证Call Clearstop_Rastscan()被执行,这说明设备2是送出了状态字的。只是因为线程的某些原因,无断点时,Call似乎被跳过了??

        ZTRSQByte = ZTSession.ReadStatusByte()     ’读设备2 状态字     
        If (ZTRSQByte And 64) = 0 Then Exit Sub
        If ZTRSQByte And 128 Then
                  responsstring = ZTSession.ReadString(22)
             End If
        Select Case ZTRSQByte
            Case Is = 80
                    ScanStopFlag = 2
                Call Clearstop_Rastscan()
                MsgBox("测试中止,结果未保存")
            Case Is = 81
                  ScanStopFlag = 3
                Call Clearstop_Rastscan()
                MsgBox("可能测试中止,结果未保存")
            Case Is = 82
                  ScanStopFlag = 4
                Call Clearstop_Rastscan()
                MsgBox("可能测试中止,结果未保存")
            Case Is = 83
            Case Is = 84
            Case Is = 88
                             ScanStopFlag = 1
                scan_suceed_Flag = True   ‘ 正常的结束
            Case Is = 92                                       '正常状态
                AngleIncrease_i = AngleIncrease_i + 1
            Case Is = 93
                            ScanStopFlag = 6
            Case Is = 94
                             ScanStopFlag = 7
            Case Is = 220                 '另外一种正常状态
                AngleIncrease_i = AngleIncrease_i + 1
        End Select
 End Sub

其中,需要停止时,调用的Clearstop_Rastscan()函数如下:

 Private Sub Clearstop_Rastscan()
        Dim toclear As Byte
        Timer1.Stop() '停止计时器
        ’对设备的一些其他操作,略去。。。
         mbSession.Clear()
        mbSession.Dispose()    ' 释放设备1
        PictureBox1.Enabled = True
        PictureBox2.Enabled = False
        GroupBox8.Enabled = True
        STOPFLAG = True
    End Sub


Timer的函数如下:

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Static finished As Boolean = True
        Dim scanpoint As Integer
        Dim RECval As Single
        Dim realpart As Double, imgpart As Double
        Dim scanstoppoint As Single
        Dim Thisrunstop As Boolean = False, Unkownstop As Integer = 0
        Dim nowP As Single
        Dim i As Integer
        Dim Ydata() As Single
        Dim filepath As String
        Dim ZTcondition(5) As Byte
        Dim toclear As Byte
        scanstoppoint = Val(Scanstop.Text)
        If STOPFLAG Then                                            ‘这是手动点击停止按键时的处理。
            ZTSession.DisableEvent(MessageBasedSessionEventType.ServiceRequest, EventMechanism.Handler)   
            PictureBox1.Enabled = True
                   mbSession.Dispose()
            PictureBox2.Enabled = False
            GroupBox8.Enabled = True
            Timer1.Stop()
            MsgBox("测试被提前中止,请等待彻底停止")
                 ZTSession.Dispose()
        Else

            If finished Then                       '如果timer1的间隔内完成了读数画图
                finished = False
                scanpoint = Math.Abs((Scanstart.Text - Scanstop.Text) / Scanstep.Text) + 1
                ReDim Ydata(scanpoint - 1)
                Dim tempt As New Stopwatch
                Dim weishu As Integer
                Select Case scanpoint * 8
                    Case Is >= 100000
                        weishu = 6
                    Case Is >= 10000
                        weishu = 5
                    Case Is >= 1000
                        weishu = 4
                    Case Is >= 100
                        weishu = 3
                    Case Is >= 10
                        weishu = 2
                    Case Is >= 1
                        weishu = 1
                End Select
                Dim aaa(8 * scanpoint + weishu + 2) As Byte
                TChart1.AutoRepaint = True
                RadationPT.Clear()                '清除当前数据
                mbSession.Write(ReplaceCommonEscapeSequences("CALCulate:DATA? SDATA\n"))
                tempt.Start()
                aaa = mbSession.ReadByteArray(8 * scanpoint + weishu + 3)
                Dim scanstartv As Single, scanstepv As Single
                Dim tempx As Single
                scanstartv = Scanstart.Text
                scanstepv = Scanstep.Text * Math.Sign(Scanstop.Text - Scanstart.Text)
                For i = 0 To (scanpoint - 1)
                    realpart = System.BitConverter.ToSingle(aaa, i * 8 + weishu + 2)
                    imgpart = System.BitConverter.ToSingle(aaa, i * 8 + weishu + 6)
                    RECval = realpart * realpart + imgpart * imgpart
                    RECval = 10 * Math.Log10(RECval)
                    Ydata(i) = RECval
                Next
                RadationPT.Add(Sectormod1_Xdata, Ydata)  ' 执行到此处时,Tchart理应自动更新绘图了。
                My.Application.DoEvents()             ‘这里是使用的Tchart,此处等待是为了界面上更新绘图。 
                finished = True
            End If
        ' 没有点停止!,确定设备2 的状态是否正常完成,如已经正常完成,也停止所有操作。
        If scan_suceed_Flag Then
                Timer1.Stop()                                   '停时间触发
            MsgBox("测试成功结束,结果已经存入文件")
            ’此处已经省略其他文件操作
            STOPFLAG = True                                              '停止计时器
            PictureBox1.Enabled = True
         ZTSession.DisableEvent(MessageBasedSessionEventType.ServiceRequest, EventMechanism.Handler) 
       '停止设备2的事件触发
            ZTSession.Dispose()
            mbSession.Dispose()
            PictureBox2.Enabled = False
            GroupBox8.Enabled = True
            scan_suceed_Flag = False
        End If
        End If
     End Sub


可能程序有点乱,希望大家能耐心帮我看看。。

重复一下我的问题,说白了,就是设备2的事件触发来的比较频繁时,不能正常的判断设备2 的状态,并响应 Clearstop_Rastscan()函数。。
 
------解决思路----------------------
看你的程序,首先并不知道是如何触发事件程序OnServiceRequest的,从表面看timer倒是定时触发的
------解决思路----------------------
是不是可以开多一个线程,将设备2的timmer的间隔足够短就可以了呢
------解决思路----------------------
你都没用线程,Timer还是在同一个线程里边,还是一步一步执行的。。。
也可以异步委托啊
  相关解决方案