将数据从全局线程传递到Win窗体VB.Net

时间:2017-06-01 04:44:10

标签: vb.net multithreading winforms

我编写了一个包含两种形式的程序

  1. FrmMain - 这是主要形式
  2. FrmTreeView - 这是子表格
  3. 在FrmTreeView中,我有一个创建getData对象的方法,并放入名为_MyPoolingThreads的全局变量,该变量的类型为List(of getData)_MyPoolingThreads是一个可以从任何形式访问的全局变量。

    getData类中,我使用了每秒滴答的线程计时器,并使用MODBUS RTU协议从我的设备中获取数据。成功从设备中获取数据后,我需要在主表单FrmMain上显示此数据。您能否建议我如何实现这一机制?

    以下是FrmTreeView的代码:

    Imports System.Threading
    Imports WeifenLuo.WinFormsUI.Docking
    
    Public Class frmTreeView
                 Inherits DockContent
    
    Private Sub cmsConnectionStartPooling_Click(sender As Object, e As EventArgs) Handles cmsConnectionStartPooling.Click
        Dim _node = _CheckConnectionNode(tvNodes.SelectedNode)
    
        If Not IsNothing(_node) Then
            Dim _threadObject = _GetDataObject(_node) 
    
            If IsNothing(_threadObject) Then
                _threadObject = New getData(_node, tvNodes) 'Here getData Object is created and added to _MyPooligThreads
                _MyPoolingThreads.Add(_threadObject)
                _threadObject.StartPooling(True)
            Else
                _threadObject.StartPooling(True)
            End If
        End If
    End Sub
    
    End Class
    

    以下是getData类的代码:

    Public Class getData
    
    'Thread Timer
    Private _ThreadTimer As Timer
    Public Property _TimerStarted As Boolean
    
    Public Sub New(ByRef connNode As ConnectionNode, ByRef tv As TreeView)
        _Name = connNode.DataItem.id.ToString
        _connectionNode = connNode
        _tv = tv
    
        Handle_ComPortEventDelegate = New Handle_ComPortEventSUB(AddressOf Handle_ComPortEvent)
        Handle_PollEventDelegate = New Handle_PollEventSUB(AddressOf Handle_PollEvent)
    End Sub
    
    
    Private Function _InitMBControl() As Boolean
        'Do init Stuff
    End Function
    
    Public Sub StartPooling(val As Nullable(Of Boolean))
        If Not IsNothing(val) Then
            If val Then
                If IsNothing(_ThreadTimer) Then
                    If _InitMBControl() Then
                        _ThreadTimer = New Timer(New TimerCallback(AddressOf _GetData), Nothing, 0, Timeout.Infinite)
                        _TimerStarted = True
                    Else
                        _TimerStarted = False
                    End If
                Else
                    _ThreadTimer.Change(_GetPollDelay, Timeout.Infinite)
                    _TimerStarted = True
                End If
            End If
    
        Else
            If _TimerStarted Then
                _ThreadTimer.Change(_GetPollDelay, Timeout.Infinite)
            Else
                _tv.Invoke(Handle_ComPortEventDelegate, New Object() {New MyEventArgs With {.EvenyType = MyEnums.MyPrivateEvents.POOLING_STOPPED}})
            End If
        End If
    End Sub
    
    
    Private Sub _GetData(ByVal state As Object)
        _ThreadTimer.Change(Timeout.Infinite, Timeout.Infinite)
    
        Dim _dataTS As Date = Date.Now
    
        Select Case _connectionNode.DataItem.conn_type
            Case MyEnums.ConnectionType.MODBUS_RTU
    
                If _connectionNode.Nodes.Count > 0 Then
                    Dim _nd As DeviceNode = CType(_connectionNode.Nodes(0), DeviceNode)
                    While _TimerStarted And Not IsNothing(_nd)
                        If Not _nd.DataItem.skip And _nd.TimeOutCount <= 3 Then
                            _GetModbusRTUData(_nd, _dataTS)
                        Else
                            _nd.SkipCount = _nd.SkipCount + 1
                            If _nd.SkipCount > _nd.TimeOutCount * 2 Then
                                _nd.SkipCount = 0
                                _nd.TimeOutCount = 0
                            End If
                        End If
    
                        If Not IsNothing(_nd.NextNode) Then
                            _nd = CType(_nd.NextNode, DeviceNode)
                        Else
                            _nd = Nothing
                        End If
                    End While
                End If
    
            Case MyEnums.ConnectionType.MODBUS_RTU_OVER_TCP
    
            Case MyEnums.ConnectionType.MODBUS_TCP
        End Select
    
        StartPooling(Nothing)
    End Sub
    
    Private Sub _GetModbusRTUData(ByRef _var As DeviceNode, ByVal _ts As DateTime)
        Dim _modbusData = New Short(_var.DataItem._GetQty) {}
    
        _modbusRTUResult = _modbusRTU.ReadHoldingRegisters(CByte(_var.DataItem.modbus_id),
                                                           CUShort(_var.DataItem.modbus_start_address),
                                                           CUShort(_modbusData.Length - 1), _modbusData)
    
        Select Case _modbusRTUResult
            Case MBS.Result.SUCCESS
                _tv.Invoke(Handle_PollEventDelegate, New Object() {New MyEventArgs With {.MyNode = _var,
                                                                                         .valueDate = _ts,
                                                                                         .EvenyType = MyEnums.MyPrivateEvents.DATA_RECEIVED}})
                For Each chnl As ChannelNode In _var.Nodes
                    chnl.DataItem.DataVal = _GetChannelData(chnl, _modbusData)
                    _tv.Invoke(Handle_PollEventDelegate, New Object() {New MyEventArgs With {.MyNode = chnl,
                                                                                             .valueDate = _ts,
                                                                                             .EvenyType = MyEnums.MyPrivateEvents.CHANNEL_DATA_RECEIVED}})
    
                    **'I want to pass data received here to FrmMain**                                                                        
                Next
            Case MBS.Result.RESPONSE_TIMEOUT
    
    
            Case MBS.Result.WRITE
    
            Case MBS.Result.ISCLOSED
    
        End Select
    End Sub
    
    Private Function _GetChannelData(ByRef chnl As ChannelNode, ByRef _dt As Short()) As Decimal
     'Do stuff here
    End Function
    
    Private Delegate Sub Handle_ComPortEventSUB(e As MyEventArgs)
    Private Handle_ComPortEventDelegate As Handle_ComPortEventSUB
    Private Sub Handle_ComPortEvent(e As MyEventArgs)
    
    End Sub
    
    Private Sub ClearPortAndTimerThread()
    
    End Sub
    
    
    
    Private Delegate Sub Handle_PollEventSUB(e As MyEventArgs)
    Private Handle_PollEventDelegate As Handle_PollEventSUB
    Private Sub Handle_PollEvent(e As MyEventArgs)
    
    End Sub
    End Class
    

0 个答案:

没有答案