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 wont 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. Its just lost the reference to the pipe to that specific browser.
Its as if you had created a timer in the app and not on the webPage, that timers action event isnt 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 wont work because it cant 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 arent 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 wont work.
You dont have to do anything else with the ctx variable, just setting any local is enough to get it working again. Im still not explaining this very well, but then I dont understand it very well honestly sum it up like this, without that line of code pushing changes to the web page from that event wont work reliably. Once you do that youre 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!
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.
[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 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. Its doing something under the hood there and that freaks me out Well… not really anymore Ive 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 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 its 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 wont 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.
[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 didnt 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 its attached to shouldnt it? But it doesnt. I didnt hit a single problem until I tried to set the URL field of am HTML viewer on the web page and that wouldnt work no matter what. All regular control changes did work. I dont 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 didnt see it on day one because things appeared to work. Which just amplifies my suggestion of Voodoo
As far as keeping references… That confuses me further, if I embed container controls I HAVE to keep a reference to them dont 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 its 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 doesnt waste time trying to push something to a control that isnt 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?