web edition accessing sessions.

Im trying to make a busy icon visible in a WE application from a thread. i have it working from timers but im sure a thread would be a faster and neater solution.
Here is the code

For i As Integer = 0 To App.SessionCount - 1
Dim context As New WebSessionContext(App.SessionAtIndex(i))
if session=App.SessionAtIndex(i) then
App.SessionAtIndex(i).webpage1.busyicon.visible=true
end if
next

However, when i run the thread it does not make the icon visible. Any ideas anyone?
It would be better if I could just say iconname visible, so it works on any page without having to name the page.

Dave

Make it visible first and then start the thread.

The way you’re doing this now, the command to make it visible is queued with the rest of the results and sent when it’s done.

Is busyscreenicon a new control you’ve added while trying to get this working?

If so, what’s happening is this…

  1. busyscreenicon.Visible=true is added to the queue of commands to be sent to the browser.
  2. SQL runs for 3 seconds.
  3. busyscreenicon.Visible=false is added to the queue of commands to be sent to the browser.
  4. The function ends and the commands are sent to the browser.

The net result is that busyscreenicon is never shown.

What you need to do is…

  1. Set busyscreenicon to visible.
  2. Start thread that runs SQL.
  3. When thread completes, hide busyscreenicon.

This way the function that set the busyscreenicon visible completes after the thread is started and the browser is told to make the icon visible. When the thread finishes its long process it tells the icon to go away.

Of course, you can use AddHandler to set a specific function to handle the Run event.

You have a thread and you try to find a session in it?

if session=App.SessionAtIndex(i) then
end if

is “session” even accessible here?

Try:

For i As Integer = 0 To App.SessionCount - 1
Dim context As New WebSessionContext(App.SessionAtIndex(i))
if session.available then
if session=App.SessionAtIndex(i) then
App.SessionAtIndex(i).webpage1.busyicon.visible=true
end if
end if
next

Your best thing is to not use the thread, enhance the code so it be as fast as possible.
Or use the thread but don’t use “session.” in the app class or any global module.

You can add a property to your session perhaps and set a specific value. Then use App.SessionAtIndex(i) to get the session and perhaps you can read the property. then do actions.

I thought every session is running in it’s own thread already.

Not true for web. The problem of updating UI from a thread is a desktop restriction. It does not apply to web apps.

To expand on this: remember you are talking about two separate processes,running on two machines over what is essentially a connectionless protocol where communication is always initiated by the client.

If you use a WebThread you have access to the Session that it was instantiated from. No need for looping through the global Sessions to find current Session and setting WebSessionContext, and no need to add the current session to a subclass property.

http://developer.xojo.com/webthread

If however you want to use a classic Thread, then setting a “CurrentSession” property on a Thread subclass will get you a long way if you need to access to it.

In either case, you should always check that the Session is still available before accessing it.

[quote=296551:@Ian Jones]If you use a WebThread you have access to the Session that it was instantiated from. No need for looping through the global Sessions to find current Session and setting WebSessionContext, and no need to add the current session to a subclass property.

http://developer.xojo.com/webthread

If however you want to use a classic Thread, then setting a “CurrentSession” property on a Thread subclass will get you a long way if you need to access to it.

In either case, you should always check that the Session is still available before accessing it.[/quote]
For anything that needs to know about the session it was created from, use a WebThread. They’re designed specifically for this and the only difference between WebThread and Thread is a WeakRef in the framework so we can tell which Session it belongs to.

Be very careful with AddHandler. They create references which can result in memory leaks when used with WebThreads (or threads for that matter). If you do use them, make sure you have a mechanism to call RemoveHandler at the end of the Run event. Using the Destructor won’t work because the reference created by AddHandler will prevent the Destructor from ever firing.

My suggestion is to subclass WebThread which uses a delegate for executing the code that you want because it’s as simple as making the Delegate property Nil when you’re done. But make sure you have an instance attached to every session, because they are Session specific.

Does that mean that It’s ok to not RemoveHandlers for non Threads?

Does that also apply if using WeakAddressOf?

I know it’s kind of backwards, but wondered whether using WeakAddressOf would allow the WebThread to destruct without having to RemoveHandler?

No.

[quote=296672:@Ian Jones]Does that also apply if using WeakAddressOf?

I know it’s kind of backwards, but wondered whether using WeakAddressOf would allow the WebThread to destruct without having to RemoveHandler?[/quote]
Well… as I recall you still have a handler pointed at the event, but now there’s no target object. All you’re doing is making it so the target can still be released. You also may get an exception if the event is raised and the target has gone nil, but I’m not near my computer to check at the moment.

No worries.

I’m always very careful to check whether the target of a WeakAddressOf is still around before accessing it, and removing the reference if not. Sounds like my rather defensive style of programming isn’t over the top in that case.

If Dave was to use AddHandler to specify an alternate WebThread.Run method, what would be a good strategy for removing the handler when the method completes?

I read in another post that you should call RemoveHander as the last statement in the alternate Run method.

Yes, and that works for AddressOf, but if you’ve used WeakAddressOf, the method may never get called because the object has gone away.

I’m beginning to wonder if maybe a delegate is a better solution here.

Interesting. Would you just set a WebThread subclass property of the delegate type you’ve created to the address of the method and invoke from the Run event?

Probably.

Dave, everything is queued until the current event loop completes. If you want to show a busy icon, you need to make those changes in the current loop and put your long running process into a WebThread and then write that data when it’s done.