Public Class Form1
Public f As Thread
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
f = New Thread(AddressOf draw)
f.Start()
End Sub
Private Sub draw()
Dim x As Integer = 0
Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
G.Clear(Color.White)
G.TranslateTransform(0, picEMG.Height)‘picEMG是Picturebox的名字
Do
G.DrawLine(Pens.Blue, New Point(x, y), New Point(x + 2, -(y - 10)))
x += 2
y -= 10
If y = 0 Then
y = 100
End If
If x = Me.picEMG.Width Then
G.Clear(Color.White)
x = 0
End If
Me.picEMG.Image = b
'G.Dispose()
Loop
End Sub
End Class
34 个解决方案
#1
加个sleep(10),让它画慢一点
#2
循环体中加一句application.DoEvents试试。另外你的循环没有退出条件?
#3
嗯,我是让它一直画。因为我想做一个类似于示波器的东西,所以要一直监测信号。
#4
提示未声明名称?
还有,具体加在那句话后面。谢谢老师。
#5
我覺得不是畫圖速度的問題,是它一直在循環,沒有一刻停息。
就是陷入了死循環了,在循环体中判斷滿足條件就退出循環吧。
你就算執行一個空的死循環,你的CPU也是100%的。
就是陷入了死循環了,在循环体中判斷滿足條件就退出循環吧。
你就算執行一個空的死循環,你的CPU也是100%的。
#6
loop前面
#7
System.Threading.Thread.Sleep(10)
#8
那就在do的後面加上Application.DoEvents()
然後判斷信號有沒有變更,沒有變更的話,就不需要重繪圖像,有變更才重繪。
我覺得這樣要一直循環的話,用單線程更好點。也方便控制些(可能我水平太菜,多線程好用,但是沒掌握好,使用起來還是有點麻煩)
#9
加个sleep(10),让它画慢一点
#10
加sleep画慢应该没什么效果。
[转帖]Doevents函数详解
http://www.programfan.com/blog/article.asp?id=10027
[转帖]Doevents函数详解
http://www.programfan.com/blog/article.asp?id=10027
#11
我加了doevents,但还是100%的占用率;加上sleep倒是可降低cpu占用率。
#12
嗯,确实是,但因为计算机的串口一直有数据送来,我要不断的读数据,所以必须不停的循环。或者,有什么好方法?
#13
你这是死循环,CPU没有空闲,所以肯定是100%忙,你用串口接收数据,把数据作为画图程序的参数自然不会这么忙了,因为通讯的波特率不可能是无限高的。
死循环必须加Sleep,最好加在给Image赋值的语句后面最后里,并不需要是函数的最后一句(你这个程序刚好是最后一句)。
还有,就是测试的时候,不要在Form_load中启动线程,最好搞个按钮,点按纽再启动,这样可以避免很多错误。
死循环必须加Sleep,最好加在给Image赋值的语句后面最后里,并不需要是函数的最后一句(你这个程序刚好是最后一句)。
还有,就是测试的时候,不要在Form_load中启动线程,最好搞个按钮,点按纽再启动,这样可以避免很多错误。
#14
呵呵,我現在做的就是計算機串口編程。隨時等待響應數據,發現數據及時處理,CPU的使用是0%到2%(該程序)
這與不斷讀數據沒有關係的。(串口也有個緩衝區,沒有必要接收到一個字節,馬上就對該字節處理吧?)我們大可以0.2秒去看一次有沒有數據吧?
這樣說吧:你的畫圖程序有嚴重bug,接收到數據,我只能對該圖進行一次重繪,處理完畢,必須馬上跳出循環。
另外,所謂的實時,也是相對的,如果前一次數據和后一次數據相差很小(當然不一定要和前一次比較)我們可以不進行重繪圖。或者,每隔0.5秒對圖進行一次重繪。以現在的電腦,處理這個應該是很快的。(可以用Time控件來實現。)
呵呵,我覺得你主要是要改寫繪圖函數,讓它根據接收到的數據進行一次重繪,然後改進數據的接收方式。
#15
事件触发
#16
把绘图过程写到picEmg.onPaint事件里面(不要创建Bitmap,直接在上面画),绘图内容访问一个Private变量取得,同时在检测输入的程序里更新Private变量,并调用picEmg.Refresh()
#17
串口通讯分事件驱动方式和查询方式两种方式,建议用事件驱动方式来做处理。例如4BYTE表示1个点,那就每接收4个字节触发一次,画一次。
#18
使用MSCOMM控件的话,通过设置RThreshold=每次接收的字节数来触发OnComm事件,然后在OnComm 事件中画线;使用serialport的话,通过设置ReceivedBytesThreshold=每次接收的字节数来触发DATARECEIVED事件,然后在DATARECEIVED事件中画线
#19
Private Sub draw()
Dim x As Integer = 0
Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
Dim g2 As Graphics = PicEMG.CreateGraphics
PicEMG.Image = b
g2.Clear(Color.White)
g2.TranslateTransform(0, PicEMG.Height)
G.Clear(Color.White)
G.TranslateTransform(0, PicEMG.Height) 'picEMG是Picturebox的名字
Do
G.DrawLine(Pens.Blue, New Point(x, y), New Point(x + 2, -(y - 10)))
g2.DrawLine(Pens.Blue, New Point(x, y), New Point(x + 2, -(y - 10)))
x += 2
y -= 10
If y = 0 Then
y = 100
End If
If x >= Me.PicEMG.Width Then '这里要改成>=
G.Clear(Color.White)
g2.Clear(Color.White)
x = 0
End If
'Me.PicEMG.Image = b
'G.Dispose()
Thread.Sleep(10)
Loop
End Sub
cpu占用0%,原来的G画板可以不要,不过当窗体被挡住再显示时,图像会没了
#20
加入
application.DoEvents
application.DoEvents
#21
得画慢一点,不然每画一点,PictureBox就自动重绘一次,CPU占用率就一下上去了。
#22
什么事件触发,触发什么。谢谢老师,呵呵
#23
恩,现在我就是每接收8192个byte画一次。可是画完以后还是回到了判断串口缓存是否有8192个可读byte的死循环。我把画图过程注释掉了,只剩下判断串口缓存这过程。打开任务管理器,还是100%。所以,如何画图似乎没关系,这死循环才是病根儿。呵呵,咋整啊你说?不死循环的话,花一次不就不能再画了么?
#24
你的窗口通讯是用什么实现的?
你现在用的是轮询的方式,也就是一直判断是否接收缓冲区中已经有8192个字节,达到8192个字节后进行读取并画图。这样你的程序就一直存在检测缓冲区的字节数上了。而用事件驱动方式的话,设置好参数,一旦接收缓冲区达到8192个字节后,就会触发一下事件OnComm(或DATARECEIVED)。而你只要在事件里面做如下处理就可以了:
1.设置读取字节数为8192;
2.读取8192个字节;
3.画图;
等下个8192个字节到了,会自动再次触发。这样你的程序根本就不需要循环,CPU占用也不会那么大了。
#25
处理串口的DataReceived事件!根据得到的数据再重新绘制窗体。
另外,数据最后能保存到内存中,串口得到数据就只管塞到内存里面。重绘窗体时候,读取内存中的数据来画图。记住,在Form的Paint事件中处理画图即可!不需要使用什么死循环!
另外,数据最后能保存到内存中,串口得到数据就只管塞到内存里面。重绘窗体时候,读取内存中的数据来画图。记住,在Form的Paint事件中处理画图即可!不需要使用什么死循环!
#26
我用的是它自带的Serialport组件(Dim serialPort As New IO.Ports.SerialPort)
#27
在SerialPort1_DataReceived中读取数据
#28
是这样吗?
Private Sub serialport_datareceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
Me.draw()
End If
End Sub
#29
datareceived中的注意事项额可以参考下这里:
http://blog.csdn.net/CloneCenter/archive/2007/10/24/1841891.aspx
http://blog.csdn.net/CloneCenter/archive/2007/10/24/1841891.aspx
#30
改成用SerialPort1_DataReceived接收数据了,咋还是100%的cpu占用率?
Public Class Form1
Public f As Thread
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If SerialPort1.IsOpen Then
SerialPort1.Close()
End If
With SerialPort1
.PortName = "com1"
.BaudRate = 115200
.DataBits = 8
.ReadBufferSize = 8192 * 2
End With
SerialPort1.Open()
End Sub
Private Sub draw()
Static x As Integer = 0
'Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
G.Clear(Color.White)
G.TranslateTransform(0, picEMG.Height) 'picEMG是Picturebox的名字
G.DrawLine(Pens.Blue, New Point(x, SerialPort1.ReadByte), New Point(x + 2, -(SerialPort1.ReadByte)))
x += 2
If x >= Me.picEMG.Width Then
x = 0
End If
Me.picEMG.Image = b
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
f = New Thread(AddressOf draw)
f.Start()
End If
End Sub
End Class
Public Class Form1
Public f As Thread
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If SerialPort1.IsOpen Then
SerialPort1.Close()
End If
With SerialPort1
.PortName = "com1"
.BaudRate = 115200
.DataBits = 8
.ReadBufferSize = 8192 * 2
End With
SerialPort1.Open()
End Sub
Private Sub draw()
Static x As Integer = 0
'Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
G.Clear(Color.White)
G.TranslateTransform(0, picEMG.Height) 'picEMG是Picturebox的名字
G.DrawLine(Pens.Blue, New Point(x, SerialPort1.ReadByte), New Point(x + 2, -(SerialPort1.ReadByte)))
x += 2
If x >= Me.picEMG.Width Then
x = 0
End If
Me.picEMG.Image = b
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
f = New Thread(AddressOf draw)
f.Start()
End If
End Sub
End Class
#31
ReceivedBytesThreshold没有设置成8192
#32
刚才设置了,然后又运行了一下.结果还是100%的CPU占用率。
#33
如何不断触发picturebox的paint事件?
#34
关注中...
#1
加个sleep(10),让它画慢一点
#2
循环体中加一句application.DoEvents试试。另外你的循环没有退出条件?
#3
嗯,我是让它一直画。因为我想做一个类似于示波器的东西,所以要一直监测信号。
#4
提示未声明名称?
还有,具体加在那句话后面。谢谢老师。
#5
我覺得不是畫圖速度的問題,是它一直在循環,沒有一刻停息。
就是陷入了死循環了,在循环体中判斷滿足條件就退出循環吧。
你就算執行一個空的死循環,你的CPU也是100%的。
就是陷入了死循環了,在循环体中判斷滿足條件就退出循環吧。
你就算執行一個空的死循環,你的CPU也是100%的。
#6
loop前面
#7
System.Threading.Thread.Sleep(10)
#8
那就在do的後面加上Application.DoEvents()
然後判斷信號有沒有變更,沒有變更的話,就不需要重繪圖像,有變更才重繪。
我覺得這樣要一直循環的話,用單線程更好點。也方便控制些(可能我水平太菜,多線程好用,但是沒掌握好,使用起來還是有點麻煩)
#9
加个sleep(10),让它画慢一点
#10
加sleep画慢应该没什么效果。
[转帖]Doevents函数详解
http://www.programfan.com/blog/article.asp?id=10027
[转帖]Doevents函数详解
http://www.programfan.com/blog/article.asp?id=10027
#11
我加了doevents,但还是100%的占用率;加上sleep倒是可降低cpu占用率。
#12
嗯,确实是,但因为计算机的串口一直有数据送来,我要不断的读数据,所以必须不停的循环。或者,有什么好方法?
#13
你这是死循环,CPU没有空闲,所以肯定是100%忙,你用串口接收数据,把数据作为画图程序的参数自然不会这么忙了,因为通讯的波特率不可能是无限高的。
死循环必须加Sleep,最好加在给Image赋值的语句后面最后里,并不需要是函数的最后一句(你这个程序刚好是最后一句)。
还有,就是测试的时候,不要在Form_load中启动线程,最好搞个按钮,点按纽再启动,这样可以避免很多错误。
死循环必须加Sleep,最好加在给Image赋值的语句后面最后里,并不需要是函数的最后一句(你这个程序刚好是最后一句)。
还有,就是测试的时候,不要在Form_load中启动线程,最好搞个按钮,点按纽再启动,这样可以避免很多错误。
#14
呵呵,我現在做的就是計算機串口編程。隨時等待響應數據,發現數據及時處理,CPU的使用是0%到2%(該程序)
這與不斷讀數據沒有關係的。(串口也有個緩衝區,沒有必要接收到一個字節,馬上就對該字節處理吧?)我們大可以0.2秒去看一次有沒有數據吧?
這樣說吧:你的畫圖程序有嚴重bug,接收到數據,我只能對該圖進行一次重繪,處理完畢,必須馬上跳出循環。
另外,所謂的實時,也是相對的,如果前一次數據和后一次數據相差很小(當然不一定要和前一次比較)我們可以不進行重繪圖。或者,每隔0.5秒對圖進行一次重繪。以現在的電腦,處理這個應該是很快的。(可以用Time控件來實現。)
呵呵,我覺得你主要是要改寫繪圖函數,讓它根據接收到的數據進行一次重繪,然後改進數據的接收方式。
#15
事件触发
#16
把绘图过程写到picEmg.onPaint事件里面(不要创建Bitmap,直接在上面画),绘图内容访问一个Private变量取得,同时在检测输入的程序里更新Private变量,并调用picEmg.Refresh()
#17
串口通讯分事件驱动方式和查询方式两种方式,建议用事件驱动方式来做处理。例如4BYTE表示1个点,那就每接收4个字节触发一次,画一次。
#18
使用MSCOMM控件的话,通过设置RThreshold=每次接收的字节数来触发OnComm事件,然后在OnComm 事件中画线;使用serialport的话,通过设置ReceivedBytesThreshold=每次接收的字节数来触发DATARECEIVED事件,然后在DATARECEIVED事件中画线
#19
Private Sub draw()
Dim x As Integer = 0
Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
Dim g2 As Graphics = PicEMG.CreateGraphics
PicEMG.Image = b
g2.Clear(Color.White)
g2.TranslateTransform(0, PicEMG.Height)
G.Clear(Color.White)
G.TranslateTransform(0, PicEMG.Height) 'picEMG是Picturebox的名字
Do
G.DrawLine(Pens.Blue, New Point(x, y), New Point(x + 2, -(y - 10)))
g2.DrawLine(Pens.Blue, New Point(x, y), New Point(x + 2, -(y - 10)))
x += 2
y -= 10
If y = 0 Then
y = 100
End If
If x >= Me.PicEMG.Width Then '这里要改成>=
G.Clear(Color.White)
g2.Clear(Color.White)
x = 0
End If
'Me.PicEMG.Image = b
'G.Dispose()
Thread.Sleep(10)
Loop
End Sub
cpu占用0%,原来的G画板可以不要,不过当窗体被挡住再显示时,图像会没了
#20
加入
application.DoEvents
application.DoEvents
#21
得画慢一点,不然每画一点,PictureBox就自动重绘一次,CPU占用率就一下上去了。
#22
什么事件触发,触发什么。谢谢老师,呵呵
#23
恩,现在我就是每接收8192个byte画一次。可是画完以后还是回到了判断串口缓存是否有8192个可读byte的死循环。我把画图过程注释掉了,只剩下判断串口缓存这过程。打开任务管理器,还是100%。所以,如何画图似乎没关系,这死循环才是病根儿。呵呵,咋整啊你说?不死循环的话,花一次不就不能再画了么?
#24
你的窗口通讯是用什么实现的?
你现在用的是轮询的方式,也就是一直判断是否接收缓冲区中已经有8192个字节,达到8192个字节后进行读取并画图。这样你的程序就一直存在检测缓冲区的字节数上了。而用事件驱动方式的话,设置好参数,一旦接收缓冲区达到8192个字节后,就会触发一下事件OnComm(或DATARECEIVED)。而你只要在事件里面做如下处理就可以了:
1.设置读取字节数为8192;
2.读取8192个字节;
3.画图;
等下个8192个字节到了,会自动再次触发。这样你的程序根本就不需要循环,CPU占用也不会那么大了。
#25
处理串口的DataReceived事件!根据得到的数据再重新绘制窗体。
另外,数据最后能保存到内存中,串口得到数据就只管塞到内存里面。重绘窗体时候,读取内存中的数据来画图。记住,在Form的Paint事件中处理画图即可!不需要使用什么死循环!
另外,数据最后能保存到内存中,串口得到数据就只管塞到内存里面。重绘窗体时候,读取内存中的数据来画图。记住,在Form的Paint事件中处理画图即可!不需要使用什么死循环!
#26
我用的是它自带的Serialport组件(Dim serialPort As New IO.Ports.SerialPort)
#27
在SerialPort1_DataReceived中读取数据
#28
是这样吗?
Private Sub serialport_datareceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
Me.draw()
End If
End Sub
#29
datareceived中的注意事项额可以参考下这里:
http://blog.csdn.net/CloneCenter/archive/2007/10/24/1841891.aspx
http://blog.csdn.net/CloneCenter/archive/2007/10/24/1841891.aspx
#30
改成用SerialPort1_DataReceived接收数据了,咋还是100%的cpu占用率?
Public Class Form1
Public f As Thread
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If SerialPort1.IsOpen Then
SerialPort1.Close()
End If
With SerialPort1
.PortName = "com1"
.BaudRate = 115200
.DataBits = 8
.ReadBufferSize = 8192 * 2
End With
SerialPort1.Open()
End Sub
Private Sub draw()
Static x As Integer = 0
'Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
G.Clear(Color.White)
G.TranslateTransform(0, picEMG.Height) 'picEMG是Picturebox的名字
G.DrawLine(Pens.Blue, New Point(x, SerialPort1.ReadByte), New Point(x + 2, -(SerialPort1.ReadByte)))
x += 2
If x >= Me.picEMG.Width Then
x = 0
End If
Me.picEMG.Image = b
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
f = New Thread(AddressOf draw)
f.Start()
End If
End Sub
End Class
Public Class Form1
Public f As Thread
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If SerialPort1.IsOpen Then
SerialPort1.Close()
End If
With SerialPort1
.PortName = "com1"
.BaudRate = 115200
.DataBits = 8
.ReadBufferSize = 8192 * 2
End With
SerialPort1.Open()
End Sub
Private Sub draw()
Static x As Integer = 0
'Dim y As Integer = 100
Dim b As Bitmap = New Bitmap(Me.picEMG.Width, Me.picEMG.Height, Imaging.PixelFormat.Format32bppArgb)
Dim G As Graphics = Graphics.FromImage(b)
G.Clear(Color.White)
G.TranslateTransform(0, picEMG.Height) 'picEMG是Picturebox的名字
G.DrawLine(Pens.Blue, New Point(x, SerialPort1.ReadByte), New Point(x + 2, -(SerialPort1.ReadByte)))
x += 2
If x >= Me.picEMG.Width Then
x = 0
End If
Me.picEMG.Image = b
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If SerialPort1.BytesToRead >= 8192 Then
f = New Thread(AddressOf draw)
f.Start()
End If
End Sub
End Class
#31
ReceivedBytesThreshold没有设置成8192
#32
刚才设置了,然后又运行了一下.结果还是100%的CPU占用率。
#33
如何不断触发picturebox的paint事件?
#34
关注中...