System.Threading.Timer线程的问题

youyiyang 2016-03-13 08:30:35
各位好,
我在做一个串口调试工具的时候,需要用到System.Threading.Timer,并且也能够通过下面代码定时发送串口数据包,

Dim autoEvent As New AutoResetEvent(False)
Dim SendingPacket1 As New SendingPacket(10)
Dim i As Long
i = 0
Dim temp As String()
Dim dueTime As Integer
loadInterval()
ThreadItem1 = New System.Threading.Timer(New TimerCallback(AddressOf SimControllSending), autoEvent, 0, 0)
While i <= zzz
autoEvent.WaitOne(999999999, False)
temp = Split(Interval(i), "|")
dueTime = temp(0).Trim()
ThreadItem1.Change(dueTime, 0)
Console.WriteLine("i=" & i & ", " & Interval(i) & "ms")
Console.WriteLine(vbCrLf & "Changing period." & vbCrLf)
i += 1
End While
ThreadItem1.Dispose()
Interval = Nothing
Console.WriteLine(vbCrLf & "Destroying timer.")

现在需要在定时发串口数据包的时候,将这些报文记录到DataGridView上面。
现在做的是,我开了两个SerialPort,分别对应RS232和RS232_2, RS232上定时发包,RS232_2上接收。由于System.Threading.Timer定时器是在后台的线程工作的,所以RS232_2的线程需要和System.Threading.Timer,定时器的线程是一个的,否则会出现等RS232全部发送完毕后,RS232_2才接收所有的这些报文。而定时器的作用是每次发包的时间间隔是不同的,这样RS232_2上不能及时将这些间隔实时的记录到DataGridView上,而是要等这个线程结束后,在DataGridView上才一股脑的看到这些报文。
所以想请教哪位能指教一下,怎么将RS232_2的线程和System.Threading.Timer定时器的线程相一致?
或者是其他什么办法?

:)
...全文
373 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
youyiyang 2016-04-05
  • 打赏
  • 举报
回复
谢谢!没有重置。
Poopaye 2016-04-05
  • 打赏
  • 举报
回复
引用 10 楼 youyiyang 的回复:
@shingoscar,再执行一遍为啥没有反应呢?
你有重置SimControllerSendCount吗?
youyiyang 2016-04-05
  • 打赏
  • 举报
回复
@shingoscar,再执行一遍为啥没有反应呢?
Poopaye 2016-04-05
  • 打赏
  • 举报
回复
toSendPacket运行完了线程就完了,不需要语句来结束
youyiyang 2016-04-05
  • 打赏
  • 举报
回复
@shingoscar,@sp1234: 原因可能是出在我要发的报文是一个excel文件,.csv的文件,我需要从csv文件的每一行读出要发的报文和发下面那行的报文需要等待的秒数。我把报文和等待的时间从csv读入到一个数组Interval(),然后再通过Split把报文和时间分别取出,在System.Threading.Timer进行定时发送。 现在我改了一下代码,Thread.Start()启动

 Public Sub btnRun_Click(sender As Object, e As EventArgs) Handles btnRun.Click
        Dim Thread1 As New System.Threading.Thread(AddressOf toSendPacket)
        'Dim Thread2 As New System.Threading.Thread(AddressOf toReceivePacket)
        Thread1.Start()
  End Sub

Public Sub toSendPacket()
        Dim temp, bOutHexTemp As String()
        Dim Buf As String
        Dim bDataOut As Byte()
        Dim Encode1 As Encoding = Encoding.ASCII
        Dim SendPer As Integer
        SendPer = 0
        loadInterval()

        While SimControllerSendCount <= zzz
            temp = Split(Interval(SimControllerSendCount), "|")
            Buf = temp(1).ToString().Trim()
            If ChboxHex1.Checked = True Then '以16进制方式发送
                bOutHexTemp = Split(Buf, " ")
                ReDim bDataOut(bOutHexTemp.Count - 1)
                For i = 0 To bOutHexTemp.Count - 1
                    bDataOut(i) = Val("&H" & bOutHexTemp(i))
                Next
                SendPer = bDataOut.GetLength(0)
            Else '以ASCII码方式发送
                bDataOut = Encode1.GetBytes(Buf)
                SendPer = bDataOut.GetLength(0) '发送总字节数  
            End If
            iSentCount += SendPer
            labelSentBytes.Text = iSentCount
            RS232.Write(bDataOut, 0, SendPer)
            SimControllerSendCount += 1
            '把在com1上发送的报文写入DataGridView2中
            Dim dr As DataRow = dt2.NewRow()
            dr(0) = mPortName
            dr(1) = Format(Now(), "hh:mm:ss") & "." & Microsoft.VisualBasic.Right("0" & Now().Millisecond.ToString(), 3) & "s"
            dr(2) = Buf
            dt2.Rows.Add(dr)
            Me.DataGridView2.DataSource = dt2
            Threading.Thread.Sleep(temp(0))
        End While

    End Sub
然后偷懒用

CheckForIllegalCrossThreadCalls = False '允许跨线程运行
现在能出现原来期望的效果,但是这个线程做完工作,用什么语句来结束呢?
Poopaye 2016-03-14
  • 打赏
  • 举报
回复
设备是怎样的?照道理1个串口就能同时完成收发工作了。 发数据是在Timer里发送 那收数据一样啊,在这个Timer里调用接收方法,或者再创建个新的Timer接收不就好了?
youyiyang 2016-03-14
  • 打赏
  • 举报
回复
引用 1 楼 shingoscar 的回复:
RS232和RS232_2在一个程序里? 自己给自己发数据????
是这样的,这个应用里需要2个串口分别从外面接收数据,所以就new了2个SerialPort,但是后来同事说,其中一个串口是用来模拟发数据报文,一个串口是用来接收外面处理器处理后发出的数据报文,所以就变成了一个发一个收了。所以我在这个程序里就处理成将发的数据放到DataGridView里面,查看发的数据报文是否是正确的。 以前这个发数据包是单独一个程序,就是用System,Threading.Timer来做的,当时也是为了赶时间就用了这个定时器,因为要做成定时间隔每次是不同的,在论坛里问了高手似乎只能用System.Threading.Timer可以做到。但是这个是后台的线程,而程序是Winform的,所以就出现发的数据一股脑的把所有的报文放到DataGridView上面了。
youyiyang 2016-03-14
  • 打赏
  • 举报
回复
@sp1234,谢谢回复,我对线程什么的不是很了解,所以出现这个问题了 我好好看看@sp1234写的,如果有问题向你请教哦!
youyiyang 2016-03-14
  • 打赏
  • 举报
回复
@shingoscar, 设备是一个控制器和汽车CAN总线。这个程序本来准备运行在PC上,一个串口连CAN总线,一个串口连控制器的输出上面,现在用前面做的那个软件来模拟CAN总线,所以一个串口就用在发送数据了
  • 打赏
  • 举报
回复
好比如说有代码
dim a = 1
dim b = a +1
你偏要降地一条代码放到一个子线程中,然后第二条代码在另一个线程(包括UI主线程),然后在第二条代码之前用一个 WaitOne 语句来阻塞着,这有意义吗? 这是非常恶劣的 WaitOne 用法。这用线程语法,模拟着顺序同步操作,是无意义的。
  • 打赏
  • 举报
回复
完全不应该写什么while 循环、阻塞代码。 你的代码是类似这样的逻辑
Dim ThreadItem1 As System.Threading.Timer
ThreadItem1 = New System.Threading.Timer(Sub()
                                                SimControllSending(xxxx)
                                                temp = Split(Interval(i), "|")
                                                dueTime = temp(0).Trim()
                                                Console.WriteLine("i=" & i & ",   " & Interval(i) & "ms")
                                                Console.WriteLine(vbCrLf & "Changing period." & vbCrLf)
                                                i += 1
                                                If i <= zzz Then
                                                    ThreadItem1.Change(Threading.Timeout.Infinite, Threading.Timeout.Infinite)
                                                    Console.WriteLine(vbCrLf & "Destroying timer.")
                                                Else
                                                    ThreadItem1.Change(dueTime, 0)
                                                End If
                                            End Sub)
纠结于线程之间相互纠缠,是个很悲哀的事情。你可以看到,根本没有必要用什么 AutoResetEvent 信号机制,根本没有必要写 while 语句,根本也没有必要写 WaitOne 代码。纯粹是自己干扰自己。
Poopaye 2016-03-13
  • 打赏
  • 举报
回复
RS232和RS232_2在一个程序里? 自己给自己发数据????

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧