Sockets within threads... am I doing this right?

Anyone who’s been paying attention to my rants on this forum knows that I really prefer synchronous socket communication, but it appears that most of the rest of the world does not… so I’m learning how to adapt. To that end I’ve been devising and testing several different ways to handle sockets asynchronously, and I’d like to get some feedback from anyone to either confirm that I’m doing things right or to help me learn a better way.

In short, I have a startup process for my app that is pretty complex, and full of lots of different decision points and states. An overview for this process looks something like this:

Many of the ovals and boxes there involve making decisions that will require accessing information provided by some WebServices (Does this user account exist? Do they have a valid subscription? Have they installed on too many other devices? Have they reached the limits imposed by their subscription in other ways? Does their local database match the data on the cloud already, etc… ). As you can see, this is not a trivial process, as it involves lots of different decisions and states.

So, my approach to implementing this with asynchronous sockets is to wrap up this entire process into a thread which has its own socket (or set of sockets) to do all the network communication. The thread tracks its own state as it moves through the registration process, and I can have a timer on the main thread (in the main window/view/whatever) that periodically checks in on the thread to see what state it is in.

Here is a sample project that demonstrates this approach. There are a few things that I’m not real comfortable doing, but am purposely trying in it to see if they are a reasonable approach or not. Specifically:

The Run method of my thread is basically a huge while loop that determines what it will do on each trip through the loop based on the state of the thread (i.e, where are we in the startup process). I’m not sure this is the “right” way to do this, and am open to suggestions.

In the Run method of this thread there are several nested while loops that essentially do nothing but wait for a response from the socket to update the step the thread is on. I’m uncomfortable with this approach, as I’m not a fan of tight loops. However, it does seem to work. I’m concerned about performance implications and want to know if there is a better way to do this.

I’m open to suggestions, criticism, wild praise, or even reckless snide remarks.

Happy Thursday!

You have to do something to make asynchronous synchronous. Except for a timeout your method looks similar to what I had when I used Python for IMAP with an interactive shell.

Don’t make the loops too tight or progress bars etc become sulky.

Silly question - could you download a bunch of this data to temporary files when the app is first launched/the user logs in then parse it at your decision points instead of downloading another chunk? It’s a completely different configuration but it might eliminate the async/sync headache you’re having since you would just have to worry about it one instead of many times.

Yeah, I assume that the best place to put a timeout would be on the timer that is watching the thread. If it stays in any particular state too long or if the whole process has taken too long I’ll kill it and take appropriate action.

Can I put the thread to sleep for a bit? Will that still let the socket events happen?

Interesting idea - in my specific case, I can probably eliminate some of the network dips by downloading a larger chunk of information at the outset, but I won’t be able to eliminate all the hits to the network.

(For instance, one of the items it checks is to see if there is a new version of my app available. This uses completely different data (and a different API endpoint) than checking to see if they have a valid subscription. )

What I did recently was put the socket in a thread but then when it was completed Raise an event that I then could decide what to do next. It’s kind of ugly, but it worked because I have to do some things in order so I might as well wait until “x” communications is done (the event) before deciding what I “x+1” is going to be.

So it’s really a asynchronous socket wrapped up in a thread with completion events to make it act synchronous. :slight_smile:

This pretty accurately describes exactly what I’ve done. I’ve subclassed HTTPSocket, and written a SocketObserver interface, which the thread implements. My subclassed socket passes the events it receives (headersReceived, pageReceived, etc) to the observer, so the thread gets informed when the socket has completed something, and it can then move from step to step.

I’m just not sure about the nested while loops in the thread. Feels … janky.

Hm…I don’t have any while loops in my thread class. I’m using the xojo.net.httpsocket but I don’t think that would make any difference.

I’m using the same class - the new httpsocket class in the xojo framework. How do you keep your thread running? i.e., how do you keep it from exiting the run event?

[quote=228900:@Kimball Larsen]This pretty accurately describes exactly what I’ve done. I’ve subclassed HTTPSocket, and written a SocketObserver interface, which the thread implements. My subclassed socket passes the events it receives (headersReceived, pageReceived, etc) to the observer, so the thread gets informed when the socket has completed something, and it can then move from step to step.

I’m just not sure about the nested while loops in the thread. Feels … janky.[/quote]
It sounds like you should use AddHandler to bind methods on the thread to the socket events you need. Allows you to keep them private, local, and gives them access to the thread’s private information.

I read somewhere else in the forum that the socket will stay alive during the lifecycle of the request. So far I’ve not had a problem with it. So you can do a Post/Get and the socket events will fire (which have been added via the AddHandler) and then in the SocketEvent handlers I figure out which events to raise. In cases where I’m doing data I just pass on the MemoryBlock in the RaiseEvent because I want my thread to do as little of that code as possible. More so I can reuse the class in other projects than any particular need on this project.

Yes, but doesn’t that blur the line pretty substantially about what is actually running in the thread and what is running on the main thread? Perhaps I’m misunderstanding, but I thought that only code that is executed in the Run event of a Thread (or called directly by it) actually executes in the thread. Methods that are called on a thread class by, say, the event handler of a socket will be executed in the main thread (though you are right that they will have access to the private stuff in the Thread).

If I understand correctly, then what is the point of using a thread at all? Is it just to break off the main thread long enough to kick of the first network request?

Take a look at their UIThreadingWithTask example /Desktop/UpdatingUIFromThread/. Basically you have a timer in the Thread that fires and you put whatever ‘stuff’ you need in a data package (we use a dictionary) that the main thread needs to take care of.

Thats right, any events from a socket always fire into the main thread. Thats true on all the desktop versions though and I assume for iOS as well. Why is a thread even necessary in this case? I’ve done multiple complicated communications sequences with whats basically a state machine and several socket subclasses that can check the state variable in their data available or error routines to know what to kick off next. It would have to be an awful lot of processing of returns and data streams before it impacted the UI or anything else and your app doesn’t have to be spinning or sleeping threads and keeping tracking of quite so many things.

If that doesn’t appeal though I wonder if you could do something with semaphores. Tell the socket to take the semaphore as it starts it’s next process and then the thread tries to get the semaphore and stops, the socket could release the semaphore when it’s got whatever data it’s waiting for and your thread continues.

[quote=228991:@Kimball Larsen]Yes, but doesn’t that blur the line pretty substantially about what is actually running in the thread and what is running on the main thread? Perhaps I’m misunderstanding, but I thought that only code that is executed in the Run event of a Thread (or called directly by it) actually executes in the thread. Methods that are called on a thread class by, say, the event handler of a socket will be executed in the main thread (though you are right that they will have access to the private stuff in the Thread).

If I understand correctly, then what is the point of using a thread at all? Is it just to break off the main thread long enough to kick of the first network request?[/quote]
You are right. But sockets will never work on a thread. So it doesn’t matter what you do here, the only purpose is code organization.

Your thread could start a request, then call Self.Suspend. In a socket PageReceived event handler on the thread, you can load the data into a property, then call Self.Resume. Your thread’s run event will pick up from after the suspend, but will have new data to work with. You could add a timer to support a timeout. This too can reside inside the thread class for convenience.

The only part of a thread that is “special” is the run event. That simply runs another stack that can be switched to. The event loop will divide some time to each stack as necessary on each iteration. Everything else in a thread should be treated as you’d treat it in any other class.

My original thought was to attempt to segregate and encapsulate all the socket calls into its own thread so that I could kick off the beginning of the state machine and then just have a timer on my main window that watches the progress of that thread. However, after some analysis it appears that the suggestions I’m getting are basically: “thread? lolz. Just slap it in its own class.”

I just want to make sure I understand correctly how to go about doing this without a thread (since it appears threading it won’t buy me anything):

I could write a class called “StartupLogic” that is essentially a big state machine. I could instantiate an instance of this StartupLogic class (let’s call the instance StarterMan) in, say, my main window. The main window could then call the entrance to the state machine method on StarterMan. StarterMan will go about doing its thing until it needs to make a network request, at which point it will make the request using a socket property that I added to the StartupLogic class. Then control returns back to the calling method in MainWindow while the socket goes off and does its thing.

When the socket receives a response, it can just bubble up the response to StarterMan, which will then both figure out what needs to happen next and update the state of the state machine, which can be watched by a timer in the main window, which in turn can update the UI.

And this is somehow “better” than a synchronous socket?

Though, I suppose I could simplify a bit by not requiring a timer to watch the StarterMan - since StarterMan is running in the Main thread it could update the UI directly… if I really wanted to couple the UI that tightly to a logic class.

I wouldn’t call that coupling if StarterMan is an instance dragged to the window layout. That is its purpose, isn’t it?

Well, I’m thinking in somewhat more abstract terms, and prefer to make things as generic as possible. For instance, let’s say I decide down the road that I don’t want the startup process to update the main window, I’d rather have it update a popup window, or perhaps have it not update any UI at all, and merely spit out some logging messages as to progress.

Just depends on which design pattern I want to try to follow. I think I would prefer to have what I like to think of as an Observer pattern in the window or whatever needs access to the startup process, so it can deal with that progress however it sees fit.

So far this example has been all about my app’s startup sequence, but there are plenty of other places it will do some relatively complex networking with a REST API, and I would prefer to let all the web service interactions happen independent of a specific window, view, or other UI element.