473,467 Members | 1,596 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

How can I safely turn this into threaded code?

I'm attempting to improve some serially executing code (that
uses the SerialPort class) bogging Windows down when it runs.
To do the 'antibogging' I'm following the example from MSDN
Windows.IO.Ports.SerialPort page and use threading.

I'm not sure if I'm creating problems with this implementation
and would appreciate your input.

The original serial code:
{
class myPacket
{
...
public bool isValid { get { ... } };
...
// append()
// scan input array (stream) for a valid packet
// set 'isValid' when complete
public append(byte[] data) { ... };
public byte[] ToByteArray() { ... };
...
}

class myComm : System.IO.Ports.SerialPort
{
public myPacket Transaction(myPacket packet)
{
myPacket response;
if (this.IsOpen)
{
// Write out the packet.
Write(packet.ToByteArray(), 0, packet.Length);

// Read until a valid packet is collected
myPacket response = new myPacket();

byte[] data;
while (!response.IsValid)
{
base.Read(data,0,this.BytesToRead);
response.append(data);
}
}
return response;
}
}
}

The class is used thusly:
{
...
myPacket Send;
myPacket Rcv;
...
myComm port = new myComm();
port.Open();
Rcv = port.Transaction(Send);
port.Close();
...
}

My attempt to 'antibog' is to add a simple thread to the
Transaction() function:

class myComm : System.IO.Ports.SerialPort
{
myPacket response;
public myPacket Transaction(myPacket packet)
{
response = null;
if (this.IsOpen)
{
// As a precaution clear out the buffer
while (this.BytesToRead 0 )
base.Read(data,0,this.BytesToRead);

// Write out the packet.
Write(packet.ToByteArray(), 0, packet.Length);

Thread rdThrd = new Thread(TransactionRead);

myPacket response = new myPacket();

rdThrd.Start();
// kill the thread when a valid packet is created
while (!response.IsValid)
{

}
rdThrd.Join();
}
return response;
}
private void TransactionRead()
{
byte[] data;

while(base.BytesToRead 0)
{
base.Read(data,0,this.BytesToRead);
response.append(data);
}
}
}
Nov 2 '06 #1
3 2166
"Jamie Risk" <risk.#.@intectus.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
I'm attempting to improve some serially executing code (that uses the
SerialPort class) bogging Windows down when it runs. To do the
'antibogging' I'm following the example from MSDN
Windows.IO.Ports.SerialPort page and use threading.

I'm not sure if I'm creating problems with this implementation and would
appreciate your input.

[code snipped]
Some thoughts:

1) Why not use SerialPort.BaseStream so that you can use the async i/o
methods (Begin/EndWrite, Begin/EndRead)?

2) Why do you create a thread, only to just sit and wait for the thread to
do the exact same thing that the in-line version of the code does? Even if
you were simply blocking the thread rather than looping (see below), this
would offer zero benefit over doing all the work in the original thread,
since the original thread is not allowed to proceed until all of the work is
done.

As far as the code you've posted goes, it has several serious problems...

One problem is that the thread will exit as soon as you first reach the
condition that there are no bytes available to read. This may or may not
occur after you've read enough data to make a valid response. If you want
the thread to remain running long enough to form a valid response, that
needs to be the condition on which the thread itself loops before exiting.

Another is that since you can't guarantee that the thread will remain
running long enough to form a valid response, the original thread may simply
block forever on the loop.

Yet another is that you are looping in the original thread. This, polling
on the status of the response, is the very worst way imaginable to wait for
another thread to do its thing. It ensures that the thread will consume
100% of its timeslice, causing it to be the primary consumer of the CPU on
the computer. This is a colossal waste of CPU time, hardly the right thing
to do if responsiveness is your goal (never mind the fact that the code
doing the looping is the original thread, negating any benefit to running
the work on another thread in the first place).

Finally, a problem that IMHO exists with your original non-threaded code is
that your code has no way to terminate gracefully should it never turn out
to receive a valid response. Basic serial hardware isn't known for being
100% reliable...unless you've got something in there to manage error
correction, transmission errors could cause your code to simply lock up.
Even if you do error correction, something like a disconnected cable or
power failure on the connected serial device could also do that. Maybe your
code isn't intended for anything serious, but if it is, it needs to
implement some sort of timeout or user-initiated cancelling mechanism so
that the code doesn't just lock up when an error occurs. This is true
whether you use the original code or some asynchronous version of it.

You aren't very clear about your goals, but it sounds as though you are
concerned that the GUI itself becomes non-responsive while waiting for the
transaction to complete. If this is the case, I think the simplest way to
address the issue is to use the async i/o methods of the Stream instance you
can get from the SerialPort.BaseStream property. This will allow you to
specify a method to be called when the i/o has completed, avoiding you from
having to deal with threading explicitly.

If you decide that instead you really need to create your thread explicitly,
or if accessing the port using the Stream model is inappropriate, you need
to fix the problems I've noted above. One particular design change you need
to do is to have the original thread simply start the i/o thread and then
get back to doing whatever it was doing. The i/o thread would then have the
logic necessary to deal with doing the entire transaction, including reading
the response, and performing whatever work has to be done once a complete,
valid response has been received. What that thread does upon completing the
transaction depends on your goals, but the simplest thing would be for it to
use Invoke to run a delegate on the main thread, allowing the main thread to
process the completed transaction as you desire.

Hope that helps...

Pete
Nov 2 '06 #2
Thanks for taking the time for posting. I appreciate your
comments and will research the BaseStream option you suggest.

- Jamie

Peter Duniho wrote:
"Jamie Risk" <risk.#.@intectus.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>I'm attempting to improve some serially executing code (that uses the
SerialPort class) bogging Windows down when it runs. To do the
'antibogging' I'm following the example from MSDN
Windows.IO.Ports.SerialPort page and use threading.

I'm not sure if I'm creating problems with this implementation and would
appreciate your input.

[code snipped]

Some thoughts:

1) Why not use SerialPort.BaseStream so that you can use the async i/o
methods (Begin/EndWrite, Begin/EndRead)?

2) Why do you create a thread, only to just sit and wait for the thread to
do the exact same thing that the in-line version of the code does? Even if
you were simply blocking the thread rather than looping (see below), this
would offer zero benefit over doing all the work in the original thread,
since the original thread is not allowed to proceed until all of the work is
done.

As far as the code you've posted goes, it has several serious problems...

One problem is that the thread will exit as soon as you first reach the
condition that there are no bytes available to read. This may or may not
occur after you've read enough data to make a valid response. If you want
the thread to remain running long enough to form a valid response, that
needs to be the condition on which the thread itself loops before exiting.

Another is that since you can't guarantee that the thread will remain
running long enough to form a valid response, the original thread may simply
block forever on the loop.

Yet another is that you are looping in the original thread. This, polling
on the status of the response, is the very worst way imaginable to wait for
another thread to do its thing. It ensures that the thread will consume
100% of its timeslice, causing it to be the primary consumer of the CPU on
the computer. This is a colossal waste of CPU time, hardly the right thing
to do if responsiveness is your goal (never mind the fact that the code
doing the looping is the original thread, negating any benefit to running
the work on another thread in the first place).

Finally, a problem that IMHO exists with your original non-threaded code is
that your code has no way to terminate gracefully should it never turn out
to receive a valid response. Basic serial hardware isn't known for being
100% reliable...unless you've got something in there to manage error
correction, transmission errors could cause your code to simply lock up.
Even if you do error correction, something like a disconnected cable or
power failure on the connected serial device could also do that. Maybe your
code isn't intended for anything serious, but if it is, it needs to
implement some sort of timeout or user-initiated cancelling mechanism so
that the code doesn't just lock up when an error occurs. This is true
whether you use the original code or some asynchronous version of it.

You aren't very clear about your goals, but it sounds as though you are
concerned that the GUI itself becomes non-responsive while waiting for the
transaction to complete. If this is the case, I think the simplest way to
address the issue is to use the async i/o methods of the Stream instance you
can get from the SerialPort.BaseStream property. This will allow you to
specify a method to be called when the i/o has completed, avoiding you from
having to deal with threading explicitly.

If you decide that instead you really need to create your thread explicitly,
or if accessing the port using the Stream model is inappropriate, you need
to fix the problems I've noted above. One particular design change you need
to do is to have the original thread simply start the i/o thread and then
get back to doing whatever it was doing. The i/o thread would then have the
logic necessary to deal with doing the entire transaction, including reading
the response, and performing whatever work has to be done once a complete,
valid response has been received. What that thread does upon completing the
transaction depends on your goals, but the simplest thing would be for it to
use Invoke to run a delegate on the main thread, allowing the main thread to
process the completed transaction as you desire.

Hope that helps...

Pete

Nov 3 '06 #3
Look at http://csharp.simpleserial.com for ideas.

Nov 21 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: aurora | last post by:
Hello! Just gone though an article via Slashdot titled "The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software" http://www.gotw.ca/publications/concurrency-ddj.htm]. It argues...
3
by: ilushn | last post by:
Help! I am having a very aggervating problem with Access. Call me lazy, but I like to copy and paste addresses from Access into microsoft work, like for sending letters where I only need about 3...
3
by: Mike Spertus | last post by:
Is there a way to get an approximate stackpointer into an int in C#? The following works, but is unsafe and adds a new variable to the stackframe: int i = (int)(&i); It seems like it should...
7
by: Stefano | last post by:
Hi all, how can I safely retrieve computer name through asp.net page's code? I'm trying with "System.Environment.MachineName", but some hosting provider doesn't allow the use of Environment. ...
3
by: Scott Emick | last post by:
I want to be able to turn off these messages in my output window The thread '<bla>' (0xaa4) has exited with code 0 (0x0). When I'm debudding multi-threaded apps it can get annoying. --...
10
by: David Zaret | last post by:
i have a dict with a particular key - the values for this key will be None, one valid scalar, or a list: {mykey, None} {mykey, "foo"} {mykey, } let's ignore the None case - in the case of...
27
by: comp.lang.tcl | last post by:
My TCL proc, XML_GET_ALL_ELEMENT_ATTRS, is supposed to convert an XML file into a TCL list as follows: attr1 {val1} attr2 {val2} ... attrN {valN} This is the TCL code that does this: set...
12
by: prism via DotNetMonster.com | last post by:
question: how do we safely remove a USB device in vb.net? for example, in the vb.net application, we open some files from a usb device, and after that, we want to "safely remove" it without...
4
by: tech | last post by:
Hi, I need to pass a block of say 320 bytes memory between some classes which do various processing on it. The app needs to be quick so i can't keep copying. The simplest way is via pointer...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.