Hidden buffer in TCPsocket?

Use a worker or diy solution using IPCSocket or using shell interactive mode (limited to lines of data)

How about the shell synchronous mode? According to what Iā€™ve read, it will suspend the main thread while it executes. If I use this shell to fetch the data input from the TCPSocket, then it should return the data to the main thread at the next line of execution.

You should NOT (ever) block the main thread in a Desktop, iOS, Web or other visual application.
Try to simplify your toughs i think you are way ovethinking. Xojo is simply a single thread (e.g. line 1ā€¦100 and back again) it handles events for you but you need to specify what your events are for
when you require a specific purpose.

A thread is just switching where the cpu is working at (still the same single cpu) and sharing the time between the main thread and other threads. A worker (or console application) is doing this on another CPU (or the same if your system is putting it that way). Now you can run things in parallel, which mean you can POLL data as long as you wish and if the expected data is there you inform the GUI using an async event.

If you want to block the main thread, i think not many are gonna help you here. Try to figure out your issue, and ask (in a new thread) how to solve that. We are here to help you out, when we have time.

We are using xojo with many devices (serial, tcp, upd etc) and never had any issue even if itā€™s expecting a flow that is like a state machine (e.g. 1 packet out, 1 packet in to be read). or any other protocol for that matter.

Thanks. Iā€™m a little busy sorting the mother of all e-mail issues for a client this week but expect I can find some time to post an example over the weekend. As @DerkJ says, I think we need to keep it simple to begin with.

I appreciate your help. I tried a number of approaches to solve my problem over a period of months before I came to the forum for help. Given that I have been using a version of RealBasic for over a decade in a variety of applications, I didnā€™t expect such a difficulty. I successfully imported an old COM port communications routine into my current program with no problems. The TCPSocket interface will not behave similarly.

Your careful description of the way Xojo works follows my understanding of it from my experience. My main thread must do things in the top/down order that I have written into a method that I call from the main thread. The problem is that I canā€™t get the method to twiddle its thumbs waiting for data. If I put it in a (tight) poll loop, it keeps the processor busy, which doesnā€™t allow time for the Socket input buffer to be filled. If I use a separate event, the method keeps executing without data. The sequence (Send queryā€”receive dataā€”process dataā€“perform other functions) is repeated numerous times throughout the method and the order of this sequence is an absolute requirement.

This sounds like you are on the wrong path?

Event based sockets:

  • In a desktop, ios or web application xojo manages the main thread for you.
  • That means xojo will poll sockets (the dataAvailable event will be called if there is data).
  • There is no need to ā€œPOLLā€ the socket yourself, but you can do that to ensure (a little) faster data retrieval.
  • You need to implement the Socket DataAvailable event, check if you expected data is there or transfer to your own buffer and then extract your data if your able to do so. If you get a DataAvailable event that would NOT mean all data is there, you can get small fragments or much more. You need to make sure you extract and use what data you need.
  • Your best way would be to create subclass of your socket and start there by creating events that only fire if there is an actual packet. This way you clear out the complexed stuff.
  • In your subclass you can do what greg suggested, use a state machine or something that only does steps when you have certain conditions met.

I suggest you start here, even if you think itā€™s different that 99,9% of all flows, itā€™s practicly not that much different since alsmost ALL protocols work the same way data ā†’ response (http etc.) you can however make a queue to have it behave as you wish but stil maintain the ease of xojo as-is.

Do you have any protocol specifications or are those unavailable ?

Yes, Wayne is still on the wrong path, stubbornly ignoring advice to use threads which can do all he needs to do easily. When the thread needs data, it suspends itself. When data is available, the dataAvailable event fires and resumes the thread, which then continues, gets the data and does the next step. and so on. Couldnā€™t be simpler.

I said all this two weeks ago.

2 Likes

By the protocol specifcation, I assume you mean the protocol for the test equipment. It is a VNA manufactured by Copper Mountain Technologies. The communications protocol is very simple:
Issue a text query command followed by a line feed
Receive a text response followed by a line feed
Response length is variable.
Response time is typically less than 200 msec

I have thought about implementing a state machine in the main thread, but the programming effort for many states would mean a lot of work. If it is the only solution to the problem, it isnā€™t a simple one. Since I have no other work for the program to be doing while waiting for a response, I keep thinking that there must be some way to have the processing wait for a response. I know that, once all methods and threads are completed, the main thread will wait forever for an input from a user. Why is there no way to have it wait 200 msec for data that it needs to parse before the next step?

I may be stubborn, but I have not ignored the advice to try to solve my problem with threads. I have tried unsuccessfully to use threads a number of times to solve this particular problem and will doubtlessly try again, as I have written numerous successful apps using threads. One of the problems that I face is that, while you insist that everything can (and should) be done with threads, I get other advice that states that threads are not the solution.

There are many ways to solve this problem, which is why youā€™re getting conflicting advice. While an async approach using DataAvailable events and a state machine is the most elegant, if you want to maintain a synchronous approach (which I would advise), use threads.

In the thread, write the command to the device, then call Thread.Pause which will yield to the main thread that services the socket and fires DataAvailable. In DataAvailable, use Thread.Resume to pass control back to the thread so it can read the results and move to the next step. Your code remains sequential and familiar, and your app remains responsive.

But then, @TimStreater already said that.

2 Likes

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

Julia, I really appreciate the time you took to give a much more complete picture of you have solved this problem.

Iā€™m thinking that ā€œStart the sequenceā€ will be a call to a thread where it can define a command, issue the command, and poll until either a timeout (error) or the expected terminating character is received. The thread can do what it needs to do with the data set received before setting up for the next command, then repeating the process as many time as necessary to complete the test routine.
Meanwhile, the UI will remain active, which is undesirable, as it should accept no user input until the thread has finished. I think that could be avoided by disabling the user control before calling the thread and enabling the user control in the thread when its work is complete.
Is there a flaw in my approach?

Thanks for clarifying what (some) others have been suggesting. Youā€™ve added a piece that was missing: "call Thread.Pause which will yield to the main thread that services the socket and fires DataAvailable ". At the point where a response is expected, it is absolutely important to have the DataAvailable event enabled. Adding this to the procedure just outlined by Julia should do the trick.
I now have the understanding of a clear path that Iā€™m anxious to try.
Thanks

I donā€™t really see any need for or benefit from threads here, but if you want to, go for it.

No need for any ā€œpollingā€ or looping. Just let your code finish. The socketā€™s events will happen without your doing anything.

By all means, disable controls that need disabling, like ā€œStartā€, and enable essential controls like ā€œCancelā€, once the sequence has been initiated by the user. This is entirely different from an unresponsive UI which happens if the main thread is in a loop, resulting in a spinning cursor, the inability to click a Cancel button, messages from the OS about your app having crashed, and bad feelings in your users.

ā€œNo need for any ā€œpollingā€ or looping. Just let your code finish. The socketā€™s events will happen without your doing anything.ā€
I have a series of query/data_response pairs to do, interspersed with command/response pairs to other equipment (through a serial port), and I need to deal with each data set separately, so I canā€™t just let the code finish without confirming the receipt of each data set as it happens. Letting it finish at its leisure and sorting it out at the end would be impossible.

I have a simple hardware SCPI tester controller, as described in the other thread. To perform a test, I need to send a SCPI Start command to the tester, wait for it to complete the test, then query it for the test results.

My subclassed SerialDeviceā€™s message parsing routine raises the following events:

GotResistance
GotCurrent
GotTime
Running
Stopped
Timeout

  1. When the operator presses the Start Test button, the UI is initialized for the test, a few SCPI setup commands are sent, then I send a SCPI Start command to tell the tester to start the test, followed by a SCPI Status query. End of button press handler, code returns to main event loop. Done.
  2. Eventually a response to the Status query will come in, which will fire either the Running or the Stopped event.
  3. In the Running event handler, I just send another Status query, because I only care about knowing when itā€™s finished. No more code, just return to event loop.
  4. At some point, a Status response of Stopped will arrive and the Stopped event fires.
  5. The event handler for Stopped sends a Resistance query. When the parser gets a response to the Resistance query, it fires the GotResistance event.
  6. The event handler for GotResistance sends a Current query.
  7. The event handler for GotCurrent sends a Time query.
  8. Now Iā€™ve got the three values I need from the test results.
  9. The event handler for GotTime calls FinishTest, which displays the results to the user, archives and uploads the results to a server, and initializes the UI for the next test.

This is admittedly a simplistic example, but it is a real-world thing actively making money on a production line as I write this, and it hopefully gives you an idea of what pure event-driven programming looks like. A better way for most cases instead of bouncing from event to event would be to have one ResponseReceived event for all messages decoded by the parser. A Select Case in that eventā€™s handler decides what to do next depending on the received message and the last query sent. Yes, the Select Case can become large, but the upside is that all of the logic that determines the behavior of the system can be in one place, and is usually pretty brute-force and therefore readable and maintainable.

Obviously I donā€™t know the details of your system and its interspersing of command/response pairs, but Iā€™m sure it can be implemented with event-driven code somehow.

Just be aware that long-running code in the Timerā€™s Action event will block the socket just as if the code were in the DataAvailable event. There are 2 ways to prevent blocking the main thread (which services the socket).

  1. Make the timer Multiple and have the timer process small chunks of the response at a time.

  2. Process the response in a thread and have the thread yield periodically.

Wayne, I think itā€™s time for you to consider hiring someone to implement this for you so you can see what a working solution looks like. Iā€™m not offering - I have my own business to run! - but I do think youā€™ll get to your goal faster and have a good foundation to build upon.

Long-running code in any event handler will block the UI. They run on the main thread.

1 Like