子线程调用主程序变量是否会发生冲突??

bigbillybear 2011-04-11 08:29:53
我是用的是VB2008,我在主线程中接收单片机蓝牙发送的数据,七个字节为一帧,最后一个字节是“E”
设置SerialPort1.ReceivedBytesThreshold = 7,进入 SerialPort1_DataReceived事件后getdatastr = (SerialPort1.ReadTo("E"))

子线程每秒运行一次,通过委托调用数据处理函数。数据处理过程判断If getdatastr.Length <> 0 Then进行相应的数据转换和处理,其中还包括为窗体label添加时间。

问题是程序开始运行还可以,但是一段时间后会出现死机现象,点击窗体的按键之类的都没反应,而且明显看到一秒循环的数据处理程序中为label改写时间没有进行,但是乱按一会貌似还能恢复运行。

所以我怀疑是不是子线程在读取getdatastr时,主线程刚好又在执行getdatastr = (SerialPort1.ReadTo("E")),造成了错误系统死机了???

刚刚接触多线程程序,还请各位大侠赐教
...全文
159 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
bigbillybear 2011-04-12
  • 打赏
  • 举报
回复
查了一下,VB里使用的是SyncLock,不知道效果如何

我修改如下

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.ReceivedBytesThreshold = 7 Then
SyncLock threadlock
getdatastr = (SerialPort1.ReadTo("E"))
End SyncLock
End If
end sub
bigbillybear 2011-04-12
  • 打赏
  • 举报
回复
之前没嵌入好,再弄一次试试
Public Class GetGPS
Private Form_R As Form1

Public Sub New(ByVal myForm As Form1)
Form_R = myForm
End Sub

Public Sub run()
Form_R.Invoke(Form_R.myDelegate_GPS)
End Sub

'主程序
Delegate Sub R_Change()
Public myDelegate_GPS As R_Change
Private myThread_GPS As Thread

Dim mythread_AS As Thread '报警子线程


Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
'委托数据处理过程
myDelegate_GPS = New R_Change(AddressOf R_GPS)
End Sub


'启动测量
Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
SerialPort1.DiscardInBuffer()
'启动报警子线程
ThreadFunction_AS()
'启动数据处理线程
myThread_GPS = New Thread(New ThreadStart(AddressOf Threadfunction_Change))
myThread_GPS.Start()
'命令单片机开始发数
SerialPort1.Write(start_command, 0, 1)
R_stop = 0
End Sub

'主程序数据接收
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim temp As Byte
'开机设置为1
If SerialPort1.ReceivedBytesThreshold = 1 Then

temp = SerialPort1.ReadByte
'如果接收到测量开始返回值,改变缓冲区字节数为7,单片机对命令有个单字节反馈
If temp = &H3D Then
SerialPort1.ReceivedBytesThreshold = 7
'发完&H3D单片机就开始发送7个字节的数据,以"E"结尾
If SerialPort1.ReceivedBytesThreshold = 7 Then
'窗体变量
getdatastr = (SerialPort1.ReadTo("E"))
End If
End Sub

'报警声音线程,跟这个问题没什么关系,但是既然问了线程的问题,也请达人看看有什么可以优化的地方吗
Private Sub ThreadFunction_AS()
mythread_AS = New Thread(New ThreadStart(AddressOf DoScanThread))
mythread_AS.Start() '开始线程
End Sub
Public Sub DoScanThread()
Do While R_ALarmSound = 1 '全局变量在数据处理过程中判断置位
If alarm_flag = True Then
SystemSounds.Question.Play()
End If
mythread_AS.Sleep(500)
Loop
End Sub


'数据处理过程
Public Sub R_GPS()

a = TimeString
b = DateString
'每秒应该更新一次时间
DT.Text = b + Space(3) + a
If getdatastr.Length <> 0 Then
'数据处理,接受GPS和标志位判断等……
End Sub

Private Sub Threadfunction_Change()
Do While R_stop = 0
Dim myGetGPS As New GetGPS(Me)
'通过GETGPS类调用委托
myGetGPS.run()
myThread_GPS.Sleep(1000)
Loop

soundbird_qian 2011-04-12
  • 打赏
  • 举报
回复
大段代码,看起来头疼,呵呵,路过飘过~帮忙顶起来
music_0000 2011-04-11
  • 打赏
  • 举报
回复
在蓝牙没有传送数据的时候,线程也是一直处在运行状态
你还是优化一下你的代码
线程应该没有问题
bigbillybear 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 karascanvas 的回复:]
楼主的不是静态对象的问题,用lock同步线程试试吧。
[/Quote]

查了一下,都是C#的代码使用的。。。。VB2008不知道有没又办法。。。。。
bigbillybear 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 karascanvas 的回复:]
楼主的不是静态对象的问题,用lock同步线程试试吧。
[/Quote]

哦??小弟刚开始搞多线程还比较门外,请问lock同步线程是什么意思啊??请赐教啊~~~
种草德鲁伊 2011-04-11
  • 打赏
  • 举报
回复
楼主的不是静态对象的问题,用lock同步线程试试吧。
bigbillybear 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 karascanvas 的回复:]
静态对象会有冲突的
[/Quote]

那要怎么避免呢???
种草德鲁伊 2011-04-11
  • 打赏
  • 举报
回复
静态对象会有冲突的
bigbillybear 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 tosp2012 的回复:]
引用楼主 bigbillybear 的回复:
所以我怀疑是不是子线程在读取getdatastr时,主线程刚好又在执行getdatastr = (SerialPort1.ReadTo("E")),造成了错误系统死机了???

應該不是這個原因造成的問題。
主程序有沒有比較大的存取操作,調試檢查一下代碼。
[/Quote]

主程序就是负责串口接受,贴点代码,大家看看吧

'定义个类
Public Class GetGPS
Private Form_R As Form1

Public Sub New(ByVal myForm As Form1)
Form_R = myForm
End Sub

Public Sub run()
Form_R.Invoke(Form_R.myDelegate_GPS)
End Sub

'主程序
Delegate Sub R_Change()
Public myDelegate_GPS As R_Change
Private myThread_GPS As Thread

Dim mythread_AS As Thread '报警子线程


Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
'委托数据处理过程
myDelegate_GPS = New R_Change(AddressOf R_GPS)
End Sub


'启动测量
Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
SerialPort1.DiscardInBuffer()
'启动报警子线程
ThreadFunction_AS()
'启动数据处理线程
myThread_GPS = New Thread(New ThreadStart(AddressOf Threadfunction_Change))
myThread_GPS.Start()
'命令单片机开始发数
SerialPort1.Write(start_command, 0, 1)
R_stop = 0
End Sub

'主程序数据接收
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim temp As Byte
'开机设置为1
If SerialPort1.ReceivedBytesThreshold = 1 Then

temp = SerialPort1.ReadByte
'如果接收到测量开始返回值,改变缓冲区字节数为7,单片机对命令有个单字节反馈
If temp = &H3D Then
SerialPort1.ReceivedBytesThreshold = 7
'发完&H3D单片机就开始发送7个字节的数据,以"E"结尾
If SerialPort1.ReceivedBytesThreshold = 7 Then
'窗体变量
getdatastr = (SerialPort1.ReadTo("E"))
End If
End Sub

'报警声音线程,跟这个问题没什么关系,但是既然问了线程的问题,也请达人看看有什么可以优化的地方吗
Private Sub ThreadFunction_AS()
mythread_AS = New Thread(New ThreadStart(AddressOf DoScanThread))
mythread_AS.Start() '开始线程
End Sub
Public Sub DoScanThread()
Do While R_ALarmSound = 1 '全局变量在数据处理过程中判断置位
If alarm_flag = True Then
SystemSounds.Question.Play()
End If
mythread_AS.Sleep(500)
Loop
End Sub


'数据处理过程
Public Sub R_GPS()

a = TimeString
b = DateString
'每秒应该更新一次时间
DT.Text = b + Space(3) + a
If getdatastr.Length <> 0 Then
'数据处理,接受GPS和标志位判断等……
End Sub

Private Sub Threadfunction_Change()
Do While R_stop = 0
Dim myGetGPS As New GetGPS(Me)
'通过GETGPS类调用委托
myGetGPS.run()
myThread_GPS.Sleep(1000)
Loop

bigbillybear 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 music_0000 的回复:]
在蓝牙没有传送数据的时候,线程也是一直处在运行状态
你还是优化一下你的代码
线程应该没有问题
[/Quote]

因为蓝牙是我控制启动的,就是说我程序现发布命令,单片机才开始发送,而且是1秒一个,我在发送命令的同时启动处理子线程,所以子线程就是一直启动的,应该不会效率太低吧
Tosp2012 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用楼主 bigbillybear 的回复:]
所以我怀疑是不是子线程在读取getdatastr时,主线程刚好又在执行getdatastr = (SerialPort1.ReadTo("E")),造成了错误系统死机了???
[/Quote]
應該不是這個原因造成的問題。
主程序有沒有比較大的存取操作,調試檢查一下代碼。

16,555

社区成员

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

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