Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interrogation organization, timeouts

I'm developing an application that works with 8 COM-ports, when data is received from one of COM-ports, the event handler is called, the application creates the wrapper for message received via COM-port, and sends it via TCP to remote host. In fact after wrapping, it becomes a command for device somewhere in ethernet-based net (start measuring command).

I'm using SerialPort and SerialDataReceivedEventHandler for working with COM-ports. The problem is that I have an timeout (0-1000 ms) specified differently for every COM-port via form. After this timeout I have to send another command to get some data from device (get data command).

  • this command is different for every of 8 COM-ports
  • this command should be sended only after receiving data via COM-port and sending first command
  • timeout between two commands is different for every com port

Have you got any suggestions about timeout organization? Thanks.

I have one idea, but I'm not sure if it possible: I have 8 event handler functions for every COM-port.

...something
sendFirstCommand();
Thread.Sleep(comPortNTimeout);
sendSecondCommand();

Can I use same construction in every of them? Won't handler for 1st port be frozen, if data Thread.Sleep() would be called in handler for 2nd port for example?

like image 691
vard Avatar asked May 30 '26 03:05

vard


1 Answers

1) Introduce some kind of CommandSourceContext class which encapsulates all parameters related to each COM port (See below)

2) To see whether handlers will freeze while an other port event has been raised - just test it in debugger and see whether all port events are invoked in the same thread. You can use Visual Studio 2010 Threads window, just put a break point in COM port event handler and see what is the current Thread Id. If you are using older Visual Studio - just log thread Id accessing it via Thread.CurrentThread.ManagedThreadId. So if events from diferent ports are invoked in the same thread - obviously handlers would block each one, otherwise would run in parallel since invoked in different threads. At least MSDN says (see at the bottom of this answer) that data received events are raised not in the main thread, so you have to be care when accessing UI controls.

interface ICommandSourceContext
{
   // Since each port has own specific command
   // we can encapsulate it in the context as well
   ICommand Command { get; }

   int PortNumber { get; }
   long TimeIntervalMilliseconds { get; }
   Action<SerialDataReceivedEventArgs> Callback { get; }     
}

// setup and add all contexts
IList<ICommandSourceContext> contexts = new List<ICommandSourceContext>();

// ideally your main code block should looks like below (this is only pseudo code)
foreach (var context in contexts)
{
   // to execute it asyncronously you can use TPL Task.Start()
   // so it would not block other handlers in case of single thread
   context.Command.Execute();
   Thread.Sleep(context.TimeIntervalMilliseconds);
}

SerialPort.DataReceived Event remarks:

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread

like image 92
sll Avatar answered Jun 01 '26 15:06

sll



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!