WebAnimator App vs Session

The docs for the AnimationComplete event for the WebAnimator control say that it fires for the Application, not the session (see quote from the docs below).

Does this mean that if you have ten people using the app and the AnimationComplete event fires, the code within would be run for all of them and not just for the individual? Or, does it just mean that you don’t have access to session-specific information during that event?

“It is important to note that this event will fire as part of the application code, rather than as part of the session code. Therefore, Session will be Nil. You may use WebApplication.SessionForControl to determine the session which owns the animator.”

Thats worded confusingly, but it does not mean that it happens in one place for all users, just that there won’t be a session reference when it happens. For whatever reason they are telling you that the event is not associated with the specific session, it still happens in that webPage object or session object or wherever else. It’s just lost the reference to the pipe to that specific browser.

It’s as if you had created a timer in the app and not on the webPage, that timers action event isn’t associated with the session that set the timers mode. You can do MOST things without a session reference, but sending some changes to the displayed page won’t work because it can’t find the pipe to the specific browser session without it. In my case I have some images being piped in on a TCP socket that need to display in the web page, but those data available events aren’t associated with any session, so when they arrive I have to find the session object for them before I try to send any updates to the page from that event.

Setting just any local variable to the app.sessionforControl in the event gets things back in sync. This is still a little like voodoo for me but this is the line of code I use at the top of such events to find the session again:

  dim ctx as new WebSessionContext(app.SessionForControl(self.Page))

Obviously that needs to go in a method that is part of a webPage or something for which self.Page is valid or it won’t work.

You don’t have to do anything else with the ctx variable, just setting any local is enough to get it working again. I’m still not explaining this very well, but then I don’t understand it very well honestly :wink: sum it up like this, without that line of code pushing changes to the web page from that event won’t work reliably. Once you do that you’re basically back to normal.

The AnimationComplete event is actually in a container control on the webpage. I wonder if the ‘dim ctx’ line has to be in the actual AnimationComplete event to get things lined up. Since Self doesn’t refer to the webpage there, I don’t think it would work. Or, would putting it in an event in the WebPage synchronize a container control within it?

Sorry for the questions, it does seem a little like voodoo to me!

Yes it does. Just pass in Self as the parameter.

Just like James’ example?

dim ctx as new WebSessionContext(app.SessionForControl(self.Page))

Just use Self instead of Self.Page

Thanks! I’ll try it!

It’s not voodoo. The issue is that to avoid cross contamination of data, each time your app runs some session specific code it must know which session it’s running under. That’s done by examining a few factors about the data coming from the client, looking up which session it belongs to and then creating a webthread associated with that session so your code can run correctly and send the response back to the correct browser.

When an event occurs on the main thread, like a Timer or a Socket event, there’s no way to tell which Session it belongs to, so you create a WebSessionContext to give the framework a hint.

Ha! I struggle just to understand the rules enough to operate within them. I can scarcely comprehend what it takes to create them! As an aside from another post, I have a lot of users running apps that all use a countdown Timer. I wonder if I should put a similar WebSessionContext reference in the Timer.Action event… maybe that’s a potential source of trouble as well.

It depends on what kind of timer it is. A webtimer is Session aware and doesn’t need it. A plain old timer on the other hand fires on the main thread and definitely does.

Just out of curiosity… how many timers do you have?

It’s a web timer. There are actually two webtimers on that screen. One counts down hours, minutes, and seconds left to complete an exam and the other fires once a minute to check and see if there are any messages to deliver to the student.

And the first fires every second?

[quote=341813:@Greg O’Lone]It’s not voodoo. The issue is that to avoid cross contamination of data, each time your app runs some session specific code it must know which session it’s running under. That’s done by examining a few factors about the data coming from the client, looking up which session it belongs to and then creating a webthread associated with that session so your code can run correctly and send the response back to the correct browser.

When an event occurs on the main thread, like a Timer or a Socket event, there’s no way to tell which Session it belongs to, so you create a WebSessionContext to give the framework a hint.[/quote]

I will be more clear :slight_smile: I totally get that you need a session reference and thread in order to send any changes that you make in that event go to the right browser! That makes total sense.

The weird part to me is that the act of looking up the session and just setting a reference to it in a local variable is enough to make it work. It’s doing something under the hood there and that freaks me out :wink: Well… not really anymore I’ve been setting it forever now but still. Just setting a local variable to something should not be enough to change huge amounts of backend stuff! Thats just very strange to me :wink: If you had called the method “linkToSessionForControl” or something like that I might have understood immediately what was going on in the background but just retrieving the session for the control then sets the thread reference or session pipe identifier for the rest of the code is weird!

and also SOME things work without the session reference. If you just create a timer in code (not a webTimer) and update a specific reference to a webLabel every second or something that works just fine! The fact you have a reference to a specific webLabel object knows the session it’s attached to. But if you have a webImageView or something like that and you try to set the URL to change what is displayed, even though you have a reference to the specific sessions display control it won’t work without the session set.

That’s correct. The first one fires every second. The second one could actually be rescheduled to every five minutes or so because I don’t use it nearly as much any more (could possibly even be removed), but the first one fires every second.

I really wouldn’t do that. If you don’t have a solid session reference and you hit a loop boundary the Session context can change on you and suddenly Webpage1.Label1 doesn’t point to the same control. Remember, just because you are calling a method on a particular control doesn’t mean that the framework won’t request the current session somewhere down the line. if that happens you’ll get SessionNotFoundExceptions.

And on the note of keeping references to controls, that’s a good way to leak entire Session objects. If the controls can’t fire their destructors, neither can the page they’re on or the Session that they’re in.

I sent you a private message about that.

[quote=342014:@Greg O’Lone]I really wouldn’t do that. If you don’t have a solid session reference and you hit a loop boundary the Session context can change on you and suddenly Webpage1.Label1 doesn’t point to the same control. Remember, just because you are calling a method on a particular control doesn’t mean that the framework won’t request the current session somewhere down the line. if that happens you’ll get SessionNotFoundExceptions.

And on the note of keeping references to controls, that’s a good way to leak entire Session objects. If the controls can’t fire their destructors, neither can the page they’re on or the Session that they’re in.[/quote]

Sorry :slight_smile: didn’t mean to suggest this was standard procedure, just this is how I discovered all this back in the beta versions of the web. A specific control instance is on a specific page which should know what session it’s attached to shouldn’t it? But it doesn’t. I didn’t hit a single problem until I tried to set the URL field of am HTML viewer on the web page and that wouldn’t work no matter what. All regular control changes did work. I don’t rely on that anymore I always grab the session when the event is coming from the main thread or any timer or socket event or anything. I just didn’t see it on day one because things appeared to work. Which just amplifies my suggestion of Voodoo :wink:

As far as keeping references… That confuses me further, if I embed container controls I HAVE to keep a reference to them don’t I? In the closed event of the windows I walk those arrays and call close on them all and that appears to work, but now it’s been so long since I looked at that I want to review it and make sure.

Things I’m doing specifically work something like this: There is a display of a graph or a video thumbnail. Updates for those images are received on a socket and should push to all currently displaying controls that want them. The container controls that display the data do so by registering themselves with the specific graph or data they want to receive, then when an update is received that walks the array of subscribed controls and pushes into them the new data, setting the session variable at the top of each one so that it goes to the right place. When those controls get their “hidden” event or their “closed” event they unsubscribe to the data so it doesn’t waste time trying to push something to a control that isn’t visible. I had THOUGHT that removing those references in the hidden events would be enough to break all those other references but maybe not? And if not then how would you get data from a main thread event like a timer or a socket to a control on a session thread?