Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将数据从全局线程传递到Win Forms VB.Net_Vb.net_Multithreading_Winforms - Fatal编程技术网

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

将数据从全局线程传递到Win Forms VB.Net,vb.net,multithreading,winforms,Vb.net,Multithreading,Winforms,我用两种形式写了一个程序 FrmMain-这是主要形式 FrmTreeView-这是子窗体 在FrmTreeView中,我有一个方法创建getData对象,并将名为\u mypooligthreads的全局变量放入其中,该变量的类型为List(of getData)\u mypooligthreads是一个全局变量,可以从任何形式访问 在getData类中,我使用了线程计时器,它每秒都在滴答作响,并使用MODBUS RTU协议从我的设备中获取数据。成功从设备获取数据后,我需要在主窗体FrmMai

我用两种形式写了一个程序

  • FrmMain-这是主要形式
  • FrmTreeView-这是子窗体
  • 在FrmTreeView中,我有一个方法创建
    getData
    对象,并将名为
    \u mypooligthreads
    的全局变量放入其中,该变量的类型为
    List(of getData)
    \u mypooligthreads
    是一个全局变量,可以从任何形式访问

    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
    
    公共类getData
    '线程计时器
    专用线程计时器作为计时器
    公共属性\u timer启动为布尔值
    Public Sub New(ByRef connNode作为ConnectionNode,ByRef tv作为TreeView)
    _Name=connNode.DataItem.id.ToString
    _connectionNode=connNode
    _电视=电视
    Handle\u ComPortEventDelegate=新的Handle\u ComPortEventSUB(Handle\u ComPortEvent的地址)
    Handle\u PollEventDelegate=新的Handle\u PollEventSUB(Handle\u PollEvent的地址)
    端接头
    私有函数_InitMBControl()为布尔函数
    “做些什么
    端函数
    公共子StartPool(val为空(布尔值))
    如果不是空(val),则
    如果是val那么
    如果没有(_ThreadTimer),那么
    如果_InitMBControl()那么
    _ThreadTimer=New Timer(New Timer callback(AddressOf _GetData),Nothing,0,Timeout.Infinite)
    _TimerStarted=True
    其他的
    _TimerStarted=False
    如果结束
    其他的
    _ThreadTimer.Change(_GetPollDelay,Timeout.Infinite)
    _TimerStarted=True
    如果结束
    如果结束
    其他的
    如果开始计时,则
    _ThreadTimer.Change(_GetPollDelay,Timeout.Infinite)
    其他的
    _Invoke(Handle_ComPortEventDelegate,New Object(){New MyEventArgs With{.EvenyType=MyEnums.MyPrivateEvents.POOLING_STOPPED}})
    如果结束
    如果结束
    端接头
    私有Sub_GetData(ByVal状态作为对象)
    _ThreadTimer.Change(Timeout.Infinite,Timeout.Infinite)
    Dim _DATTSAS Date=日期。现在
    选择Case\u connectionNode.DataItem.conn\u类型
    案例MyEnums.ConnectionType.MODBUS_RTU
    如果_connectionNode.Nodes.Count>0,则
    Dim作为DeviceNode=CType(_connectionNode.Nodes(0),DeviceNode)
    虽然时间已启动且不为空(\u nd)
    如果不是_nd.DataItem.skip和_nd.TimeOutCount _nd.TimeOutCount*2,则
    _nd.SkipCount=0
    _nd.TimeOutCount=0
    如果结束
    如果结束
    如果不是空(\u nd.NextNode),则
    _nd=CType(\u nd.NextNode,DeviceNode)
    其他的
    _nd=无
    如果结束
    结束时
    如果结束
    案例MyEnums.ConnectionType.MODBUS\u RTU\u OVER\u TCP
    Case MyEnums.ConnectionType.MODBUS_TCP
    结束选择
    起动冷却(无)
    端接头
    专用子系统GetModbusRTUData(ByRef变量作为设备节点,ByVal变量作为日期时间)
    Dim_modbusData=新短(_var.DataItem._GetQty){}
    _modbusRTUResult=_modbusRTU.ReadHoldingRegisters(CByte(_var.DataItem.modbus_id)),
    CUShort(_var.DataItem.modbus_start_address),
    CUShort(_modbusData.Length-1),_modbusData)
    选择案例_modbusrutresult
    案例MBS.Result.SUCCESS
    _Invoke(Handle_PollEventDelegate,New Object(){New MyEventArgs With{.MyNode=\u var,
    .valueDate=\u ts,
    .EvenyType=MyEnums.MyPrivateEvents.DATA_RECEIVED})
    对于每个chnl作为_var.Nodes中的ChannelNode
    chnl.DataItem.DataVal=_GetChannelData(chnl,_modbusData)
    _Invoke(Handle_PollEventDelegate,New Object(){New MyEventArgs With{.MyNode=chnl,
    .valueDate=\u ts,
    .EvenyType=MyEnums.MyPrivateEvents.CHANNEL_DATA_RECEIVED})
    **'我想将此处接收到的数据传递给FrmMain**
    下一个
    案例MBS.Result.RESPONSE\u超时
    Case MBS.Result.WRITE
    案例MBS.Result.ISCLOSED
    结束选择
    端接头
    私有函数_GetChannelData(ByRef chnl作为ChannelNode,ByRef dt作为Short())作为十进制
    “在这里做事
    端函数
    私人代理子句柄(作为MyEventArgs)
    私有句柄\u复合文本删除为句柄\u复合文本
    专用子句柄\u组件事件(e作为MyEventArgs)
    端接头
    专用子ClearPortAndTimerThread()
    端接头
    私有委托子句柄\u PollEventSUB(e作为MyEventTargs)
    私有句柄\u PollEventDelegate作为句柄\u PollEventSUB
    私有子句柄\u PollEvent(e作为MyEventArgs)
    端接头
    末级
    
    在何处以及如何定义_mypooligthreads?_mypooligthreads在模块中定义为
    _mypooligthreadsas List(Of getData)
    _MyPoolingThreads变量是在加载splash表单时启动的。。。在mainform中编写一个共享子函数,并从getData调用它。应该可以工作。@muffi-之前我已经声明了全局事件,我正在从线程中引发该事件并添加句柄