Hidden buffer in TCPsocket?

I’ve been through exactly what you’re going through. What you have to do is break your main program up into smaller pieces, each of which returns control of the program to the main event loop, so that instead of

StartTheSequence
WaitInALoop
DoTheNextThing
WaitInALoop
DoTheNextThing
etc

which will freeze your UI, you do

StartTheSequence

and that’s it. No looping, no waiting, no more code executing, no “barreling along”. Your program code returns from that to the behind-the-scenes Event Loop, which keeps the UI responsive. Whether StartTheSequence launches a thread or just sends a SCPI command is beside the point; your code needs to be event-driven either way. In many cases threads are unnecessary for simply sequencing a bunch of sequential SCPI commands and queries.

So how does your program continue? Events. Your having sent a command or query to a piece of external hardware eventually results in a response from the equipment or a timeout from a timer that you started when sending the initial query. When that response comes in or the timeout expires, your socket (preferably a subclass of the socket so you can add custom event definitions and properties and so forth to it) either parses any received data and when it finds something it recognizes it fires an event, say, “GotResponse”, or it fires the subclass’s TimeOut event.

Now in the GotResponse or Timeout event of the subclassed socket instance your program decides what to do next based on the received response or timeout. The sequencing is strictly controlled, as you require. No loops or delays are required. There’s another active thread in the forum right now where all this is being discussed, using SerialDevices instead of TCPSockets, but for the purposes of this discussion there’s no difference.

I’ll reiterate my caution about parsing in a socket’s DataReceived event. You don’t want to do that; in my experience if lengthy code is executed in the DataReceived event, the socket will miss bytes. In DataReceived you should only append the just-received bytes to a buffer string and start a short (≈2ms) one-shot timer. That timer’s action event or a method called by the Action event is where you do your message parsing and event raising, so that the socket is not encumbered and can go back to doing its thing of receiving data.

I’ll also mention in passing a really cool thing, which is an Event Bus. I use this one from Ian Jones, who I think used to be a participant here.

It’s very simple to use - any object can publish an event, and any object which conforms to the EventBusIJ interface can subscribe to any event (I think Ian used different terminology than “publish” and “subscribe”, but it’s easy to customize of you want). An event bus can really help keep an application clean - you can have various things responding to a single event like receipt of a SCPI response, without having to have explicit spaghetti code linking them all together. Want to display received responses in a listbox? Just have your listbox subclass subscribe to the ResponseReceived event.

HTH

1 Like