DoEvents in Web Apps for tight loops?

Just to be clear, this is an issue with the new xojo.Net.HTTPSocket, not the classic version.

My App is on Windows too which is why thought you were mentioning recursion as I envisaged the code would be recursive due to non-termination of the event.

Use of a timer had crossed my mind (from my old VB days) but a tight loop in a low priority thread polling a changed property added to a socket subclass with some sleep time seemed more maintainable and can be tuned.

[quote=192326:@Eric Wilson]My App is on Windows too which is why thought you were mentioning recursion as I envisaged the code would be recursive due to non-termination of the event.

Use of a timer had crossed my mind (from my old VB days) but a tight loop in a low priority thread polling a changed property added to a socket subclass with some sleep time seemed more maintainable and can be tuned.[/quote]

Why don’t you simply try the asynchronous event driven model, with the addition of the timer as suggested by Wayne ? It is simple to implement and elegant.

The tight loop model is typical of old à la QuickBasic procedural programming. Events were never intended to host tight loops that last for a long time. Tight loops do all sorts of strange things, like preventing timers Action and other events (including PageReceived) from happening. Besides, in Xojo Web, the UI does not refresh until events are over. So the need for a thread, and yet more complex code. Spaghetti instead of a simple, elegant approach.

I have no doubt that the tight loop can eventually be made to work with efforts. But is it really worth it when using Xojo.Net.HTTPSocket as it was intended in the first place is all so simple ?

I was proposing the loop to be in a thread not an event but will try what you say because it might avoid context switching, so if your method works I think it would perform better.

Thanks,

Eric

Soooo… I’m unable to test the timer yet because the PageReceived event is not firing when I send a reply from the HandleURL event on the server after successfully Sending the first Post data from the socket (to a URL also containing a querystring). The following HandleURL code fails to trigger the PageReceived event on the xojo.NET.HTTPSocket:

Request.Print "<html><body>DONE</body></html>" Request.Status = 200 // An HTTP input OK Response

Because the socket is asynchronous I get the following error when I try to send another lot of data from the web app via the HTTPSocket:

[quote]
Unhandled xojo.Core.UnsupportedOperationException
Message: A request is already in progress.[/quote]

… Which means this will need to be handled by invoking another instance of the socket subclass (once it’s all sorted…)

Any ideas why this is not happening?

[quote=192585:@Eric Wilson]Soooo… I’m unable to test the timer yet because the PageReceived event is not firing when I send a reply from the HandleURL event on the server after successfully Sending the first Post data from the socket (to a URL also containing a querystring). The following HandleURL code fails to trigger the PageReceived event on the xojo.NET.HTTPSocket:

Request.Print "<html><body>DONE</body></html>" Request.Status = 200 // An HTTP input OK Response

Any ideas why this is not happening?[/quote]

I suppose you have verified the HandleURL works as expected by pointing to it with a browser ?

I do not see the necessary Return True at the end of your code. Without it, the browser will just get an error 500.

Return True is the last line and Request.Print works in a browser from the same HandleURL event.

Just prior to the code above I write the Request.Entity to a file using a file name passed by a querystring … However I can’t trap the reply yet to trigger the timer!

A little confused…is this one web app with a socket talking to another via HandleURL?

Yep, using different ports on the same machine, firewall off.

[quote=192585:@Eric Wilson]Because the socket is asynchronous I get the following error when I try to send another lot of data from the web app via the HTTPSocket:

Unhandled xojo.Core.UnsupportedOperationException
Message: A request is already in progress.[/quote]

This is why you do not want to initiate another request before the PageReceived event took place…

Sure, but knowing this helps isolate the problem – that the socket hasn’t gone out of scope for example.

So I will try to substitute in the classic socket and see if this is a problem with the new framework only.

The classic Socket does not trap the PageReceived event either to fire the timer. However it does allow additional requests without being hung up waiting for the PageReceived Event. Don’t know if this is a good or bad thing…

Added another IP address to my machine so the two stand-alone Web Apps use different IP Addresses and Port Numbers … no difference unfortunately.

I do. Using tight loops in a web edition project almost always causes bad things, with or without DoEvents.

What you guys are trying to accomplish is counterproductive in terms of how the new socket works. It is designed to be asynchronous and I have no doubt that shoehorning it to be synchronous is going to cause problems down the road for you.

Put the calling code where you want it and call the response code in response to the PageReceived event. Use the URL or subclass the socket and add a tag of some sort. This technique won’t block the rest of your users and will cause a lot less pain down the road.

Greg is correct. The way I see it, the timer-based proposal fails because the socket seems to require a reference to its calling code context (I imagine for Post data etc.) which seems to break when a timer is set to re-call the socket. I imagine putting the calling code in a sleepy thread might also cause problems as would circular referencing back to the socket in the PageReceived event.

In the absence of this type of thing the Request.Print > PageReceived is now working fine on my machine.

The Doco at http://www.xojo.com/blog/en/2015/05/httpsocket-now-with-support-for-http-11.php states:

What then is the best approach for this when there is a queue of multiple posts to be sent sequentially, given it seems the new asynchronous socket does not accept requests while another is being processed?

You got the answer a few posts back from me and Wayne: initiate your first request which starts the socket, then do the subsequent ones in the PageReceived event, so you never send a new request while one is processed.

The new xojo.Core.Timer.CallLater method is a great way to skip out of the page received event & continue on the next transaction.

Back on this now: Michel and Wayne, I wasn’t able to get repeat posts working serially in the context of sending files on from a WebFileUploader Uploadcomplete event for possessing elsewhere. It seems timers, threads, webuploaders and httpsockets execute somewhat isolated from each other in a Standalone Web App (which itself is multithreaded for each session so I imagine the engineering required to coordinate asynchronous user codes would be non-trivial to say the least). So they don’t seem to play well together.
I also found that global properties up the call stack could become inaccessible when one asynchronous class calls another even when those were assigned to properties added to the class at each level of the stack. It may be possible to get around this by assigning data down the stack of asynchronous calls by value but I want to avoid the performance hit for large files, not to mention resource usage.
Does anyone have an example project that actually works to send HTTP posts serially directly from an array of data supplied by a webuploader?

is very simple - just have a socket per session. Add a queue per session and add to it as the files are uploaded. Process the queue sequentially. Yes with the new http socket you need to exit the pagecomplete event before reusing the socket, but the new calllater method makes that easy.

Thanks Wayne but I have tried this with the classic HTTPSocket which seems to go into hyperspace when the CallLater event fires. I suspect if the data was on disk and the code was executing in the main thread by way of a button action event it would work fine but in this case the data is held in a webfileuploader control (in a container) and fired by a downloadcomplete event and I can’t get this to work as you suggest.

To be more specific the asynchronous WebFileUploader is calling an asynchronous socket which is calling a timer and the app just seems to loose the plot.
I have tried to put a timer between the WebFileUploader and the classic HTTPSocket but the socket goes into hyperspace when called from the timer as the post data to the socket is set. When running compiled an error states that the data set is null when it has been assigned by the code, leading me to suspect some kind of boundary issue, again due to asynchronicity.

Or maybe I have missed something completely obvious?