将数据从全局线程传递到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
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-之前我已经声明了全局事件,我正在从线程中引发该事件并添加句柄