By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,190 Members | 1,412 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,190 IT Pros & Developers. It's quick & easy.

SerialPort writing byte data

P: 8
Hi,

I am currently writing a simple form application in C# that uses the SerialPort class (C# 3.5). But I have put my head in the wall several times to solve a simple problem.

I have a datagridview and each time the event on row added is run I need to send some stuff out on the serialport. I am using the SerialPort write method to write byte data.

Each times several rows are added (more than one), in the same time frame (or very near in milliseconds) I get stuck with the problem that the write method is called simultaneously which causes the SerialData send buffer to contain data spread from the different row sources which in the end will be very incorrect. After each write I also need to but a thread sleep (500 ms) otherwise results are "unknown".

I therefore implemented a singleton class(that's holds all the serial comm stuff) that run's on it's own thread and whenever serial data needs to written I put the data into a byte list in the class and the class on it's self handles to writes sequentially after each write is completed. I still need to keep the thread sleep (500 ms) but it runs in the separate thread and does not cause any problem but this solutions feel like doing plumbing.

Is this really a correct implementation or this something simpler or anybody else recommend any other approach ?

Regards,

Jens
Oct 29 '09 #1
Share this Question
Share on Google+
9 Replies


tlhintoq
Expert 2.5K+
P: 3,525
Each times several rows are added (more than one), in the same time frame (or very near in milliseconds) I get stuck with the problem
Are you doing some kind of polling loop? Is that where the "time frame" comes in?

I would expect that if you were raising an event each time you add a row, with the data as the arguments then you should be calling your SerialSend method once for each row.
Oct 29 '09 #2

Plater
Expert 5K+
P: 7,872
Depending on your situtation and time requirements, take a look at the System.Collections.Queue object. You can keep pushing things(commands for the serial port) onto it, and then on a timer or something, pullthem off and send them.
This assumes that you would push the entire message onto the queue at one time.
Oct 29 '09 #3

P: 8
tlhintoq:
I have registered my event handler on the event on row added on the datagridview which means it will be raised once for each row added. If 10 rows are added 10 serialport write commands will be issued. If I hook up this function under the event handler it will cause big time problem, I assume this is because numerous ongoing writes will get a failure in the write buffer (mixed up) , I am not sure about this - but I will not work properly. That's why I used the singleton method with "a queue handler" (a list of bytes that is processed in order, one after one).

Plater:
Thanks, will look it up now!


PS ! I honestly don't know why I need to keep a Thread.Sleep(500) after the write method. I thought the SerialPort class handled problems with concurrent calls to write. Samples and tutorials online also use the Thread.Sleep and I haven't really seen any info why this is really needed. Of course it will not work without it, but why just 500 ms ? 200 ms will not work for an example. This feels like an uknown plumbing method.

Anyone care to enlighten me about this ?
Oct 29 '09 #4

P: 8
Plater:

I quickly found out another post in another forum, let me quote (his exact words):

My initial response would be to say: create a CommInteraction class that contains a Command and a Response property. Add instances of the CommInteraction class to the output queue when commands are issued. As the worker loop ejects items from the queue and processes their Command property value, it places the response in the Response property and adds the item to the input queue. Now every response object in the input queue contains a copy of the command that caused this response. If needed you could store any additional info about the sender in the CommInteraction class that you need in order to identify it after the response is returned.


This seems like something I also would do to solve the problem, anyone else have any ideas ?
Oct 29 '09 #5

tlhintoq
Expert 2.5K+
P: 3,525
That was going to be my next suggestion:
The NewRowEvent doesn't cause a serialport write, or the create of a class object that writes.
Instead it adds to a list of things to write by the one and only class doing the writing
Oct 29 '09 #6

P: 8
tlhintoq:

I may be unclear ;-) .... but it this case I instantiate the SerialPort class during application loading and port is open from then until application closes. SerialPort is added as a private field so it can be accessed by internal methods.

So when the even on new row is fired in the same "class" I can access the SerialPort which is open and call SerialPort.write method. But just this method will not work since I get the trouble with concurrent calls if several rows are added in the very same near timeframe.

Regards,

Jens
Oct 29 '09 #7

tlhintoq
Expert 2.5K+
P: 3,525
So one serialport object: Good.
But it sounds like all your other methods can send a SerialPort.Write command whenever they like. For now it may just be the AddRow event that does it. But the event causes an immediate attempt to write.

What I was suggesting was that you put the SerialPort object into class that has a list of datalines to send. Your AddRowEvent doesn't try to Serial.Write but instead adds it's data to the list in the SerialPortControlClass. The class will then handle the actual sending at it's own pace.

This should keep the 3rd call from stepping on the 2nd call, because the SerialPortControlClass will send each item in its list in sequence. Basically this because the queue of data to be sent.
Oct 29 '09 #8

tlhintoq
Expert 2.5K+
P: 3,525
So one serialport object: Good.
But it sounds like all your other methods can send a SerialPort.Write command whenever they like: Even if the SerialPort is in the middle of a Write operation.

For now it may just be the AddRow event that tries it. Later you might have a dozen other things trying to send on the same port for different reasons.

What I am suggesting is that you put the SerialPort object into a class that has a list of datalines to send. Your AddRowEvent doesn't try to Serial.Write but instead adds it's data to the list in the SerialPortControlClass. The SerialPortControlClass will then handle the actual sending at it's own pace.

This should keep the 3rd call from stepping on the 2nd call, because the SerialPortControlClass will send each item in its list in sequence. Basically this because the queue of data to be sent.
Oct 29 '09 #9

P: 8
Good, I will setup a class using the queue microsoft class in collections to see how it works out.

Regards,

Jens
Oct 30 '09 #10

Post your reply

Sign in to post your reply or Sign up for a free account.