|
-
Mar 10th, 2010, 04:46 PM
#1
Thread Starter
Addicted Member
[RESOLVED] Class events question
I set up a class with an event as shown here :
Code:
Imports System.IO.Ports
Public Class CommPort
Dim _msg As String
Dim WithEvents SerialPort As New SerialPort
Public Sub New(ByVal portID As String)
If SerialPort.IsOpen Then
SerialPort.Close()
End If
Try
With SerialPort
.PortName = portID
.BaudRate = 9600
.Parity = IO.Ports.Parity.None
.DataBits = 8
.StopBits = IO.Ports.StopBits.One
End With
SerialPort.Open()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Public Event DataReceived(ByVal message As String)
Private Sub ReadData(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim _bytes As Integer = SerialPort.BytesToRead
_msg = ""
For i As Integer = 0 To _bytes - 1
_msg = String.Concat(_msg, Chr(SerialPort.ReadChar))
Next
RaiseEvent DataReceived(_msg)
End Sub
End Class
And from the main program am using this code :
Code:
Public Class Main
Dim WithEvents commTest As New CommPort("COM1")
Private Sub ProcessCommData(ByVal message As String) Handles commTest.DataReceived
txtSONumber.Text = message
End Sub
End Class
When the event triggers I get an error in the program where trying to update the forms text that says "Cross-thread operation not valid: Control 'txtSONumber' accessed from a thread other than the thread it was created on."
Am I using the custom event incorrectly?
Thanks in advance for your help.
-
Mar 10th, 2010, 04:58 PM
#2
Re: Class events question
No, but your custom event happens in another thread. You need to invoke a sub that changes the txtSONumber text in the UI thread.
Add this to your code:
vb.net Code:
Public Delegate Sub InvokeWithStringDelegate(ByVal Text As String) Public Sub ChangeTextboxText(ByVal Text As String) If txtSONumber.InvokeRequired Then Me.Invoke(New InvokeWithStringDelegate(AddressOf ChangeTextboxText), New Object() {Text}) Else txtSONumber.Text = Text End If End Sub Private Sub ProcessCommData(ByVal message As String) Handles commTest.DataReceived ChangeTextboxText(message) End Sub
Last edited by cicatrix; Mar 10th, 2010 at 05:03 PM.
-
Mar 10th, 2010, 05:08 PM
#3
Re: Class events question
I think the code is fine... it's just in the wrong spot...
This code:
Code:
Dim WithEvents commTest As New CommPort("COM1")
Private Sub ProcessCommData(ByVal message As String) Handles commTest.DataReceived
txtSONumber.Text = message
End Sub
Should be in the form's class... not the main class...
-tg
-
Mar 10th, 2010, 05:11 PM
#4
Hyperactive Member
Re: Class events question
 Originally Posted by techgnome
I think the code is fine... it's just in the wrong spot...
This code:
Code:
Dim WithEvents commTest As New CommPort("COM1")
Private Sub ProcessCommData(ByVal message As String) Handles commTest.DataReceived
txtSONumber.Text = message
End Sub
Should be in the form's class... not the main class...
-tg
No that isn't his problem at all, he is operating in the correct class, just not on the same thread which is why the invoking is required
He would have likely gotten an error before he compiled if he wasn't in the right class, instead of a runtime error
-
Mar 10th, 2010, 05:18 PM
#5
Re: Class events question
I get what you're saying... but I don't see how it's on a different thread, unless there's something that wasn't shared as part of the code. It's not like it would be the first time incomplete code was posted. ;P
-tg
-
Mar 10th, 2010, 05:21 PM
#6
Hyperactive Member
Re: Class events question
 Originally Posted by techgnome
I get what you're saying... but I don't see how it's on a different thread, unless there's something that wasn't shared as part of the code. It's not like it would be the first time incomplete code was posted. ;P
-tg
oh well he is using a CommPort which receives data on its own seperate thread, thus the DataReceived event is inherently on a different thread
very similar to WinSock's data receiving/connection request etc
-
Mar 10th, 2010, 05:28 PM
#7
Thread Starter
Addicted Member
Re: Class events question
Thanks cicatrix, and everyone else, for such a quick response. That took care of my error. Interesting how that works, checking for the InvokeRequired, which I've never used before, and then returning to update the textbox.
Thanks for your help!
-
Mar 10th, 2010, 05:37 PM
#8
Re: Class events question
Ahh.... OK... makes total sense then.
See? It is possible to learn something new everyday.
-tg
-
Mar 10th, 2010, 05:43 PM
#9
Re: Class events question
The solution works, but I don't like it.
The serial port already raises a datareceived event. Since you are wrapping the port in a different class, do you really want to have that class deal with events on different threads? Do you want any class (form) that uses your wrapper class to have to be aware that the datareceived event is coming in on a different thread? I would say that it would be better to raise the event on the UI thread and be done with it. Otherwise, what is the advantage to wrapping the serial port object?
If you would prefer to raise the event on the UI thread, take a look at the UDP class I posted at about #7 in this thread:
http://www.vbforums.com/showthread.php?t=509619
In particular, look at how I used the SynchronizationContext. I save the context before starting the thread (you could do that in your class constructor, which will mean that the context saved will be for the thread that created the object, though the object is not thread specific). You then add a sub that raises the actual event, and when you want to raise the event, you post a call to that sub on the context. It takes only a couple lines, and your events come out on the thread that created the class.
My usual boring signature: Nothing
 
-
Mar 11th, 2010, 08:44 AM
#10
Thread Starter
Addicted Member
Re: Class events question
Shaggy Hiker,
Thanks. I'm looking at your previous post now and reading up on SynchronizationContext. No doubt I'll have more questions.
thanks again for your input.
-
Mar 11th, 2010, 09:47 AM
#11
Thread Starter
Addicted Member
Re: Class events question
Ok, let's see if I'm getting this.
The myContext = System.Threading.SynchronizationContext.Current needs to be set from my class that is wrapping the serial port class. Then, within the SerialPort.DataReceived event of the serial port class the myContext.Post is done so that I can raise the wrapper classes custom event.
Here's what I changed:
Code:
Imports System.IO.Ports
Public Class CommPort
Dim _msg As String
Dim WithEvents SerialPort As New SerialPort
Dim myContext As System.Threading.SynchronizationContext
Public Sub New(ByVal portID As String)
myContext = System.Threading.SynchronizationContext.Current
If SerialPort.IsOpen Then
SerialPort.Close()
End If
Try
With SerialPort
.PortName = portID
.BaudRate = 9600
.Parity = IO.Ports.Parity.None
.DataBits = 8
.StopBits = IO.Ports.StopBits.One
End With
SerialPort.Open()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Public Event DataReceived(ByVal message As String)
Private Sub triggerDataReceived(ByVal state As Object)
RaiseEvent DataReceived(_msg)
End Sub
Private Sub ReadData(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim _bytes As Integer = SerialPort.BytesToRead
_msg = ""
For i As Integer = 0 To _bytes - 1
_msg = String.Concat(_msg, Chr(SerialPort.ReadChar))
Next
'RaiseEvent DataReceived(_msg)
myContext.Post(AddressOf triggerDataReceived, Nothing)
End Sub
End Class
Then, in the UI code:
Code:
Private Sub ProcessCommData(ByVal message As String) Handles commTest.DataReceived
txtSONumber.Text = message
End Sub
It works but wanted to make sure I'm using this method correctly. Since I haven't done a lot of programming, especially recently, I'd love to hear any other feedback you have on anything you see.
As always, thanks so much for the help.
-
Mar 11th, 2010, 10:24 AM
#12
Re: Class events question
I believe you have done it the way that I would have. I particularly like the fact that the event is now raised on the thread that created the wrapper for the serial port, which is where you would expect the event to be raised normally.
My usual boring signature: Nothing
 
-
Mar 11th, 2010, 10:41 AM
#13
Thread Starter
Addicted Member
Re: Class events question
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|