WebThread / Xojo.Core.Timer.CallLater and WebSession

Running into a few issues with “Exception Message: Control cannot be created because no session context is available. Create a WebSessionContext object.” This error happens randomly, I’ve been unable to produce when running the IDE so not easily been able to track down when it’s happening, been adding a lot of System.DebugLog to try and help track it down.

Does this logic sound correct

In the Shown event of WebPage I start a WebThread the WebThread has a single line of code which calls a Method, this method gets some data from a database and puts it into a Class Array, the Class Array is a property of the WebPage as is the Method that the WebThread uses.

When I get to the end of the Method being used by the WebThread I use Xojo.Core.Timer.CallLater to call a Method

Xojo.Core.Timer.CallLater(0, WeakAddressOf LoadDataComplete)

So that LoadDataComplete has access to the Session I do

[code] Dim Sess As Session = MySession

Dim Context As WebSessionContext

’ Check Session Defined
If Sess <> Nil Then

' Define Context
Context = New WebSessionContext(Sess)

End If[/code]

LoadDataComplete creates a container, does the container have access to the session?

MySession is defined in the Open Event of the WebPage.

Private mSession As WeakRef

[code]Private MySession As Session

Get
If mSession = Nil or mSession.value = Nil then
Return Nil
Else
Return Session(mSession.Value)
End If
End Get
Set
’ Set Session
mSession = New WeakRef(value)
End Set[/code]

Sub Open() ' Set Session MySession = Session End Sub

Yeah, you can’t do that. The timer fires on the main thread and has no access to the session.

I was taking the answer from this thread, regarding Xojo.Core.Timer.CallLater Is that incorrect https://forum.xojo.com/34712-websessions-and-xojo-core-timer-calllater/0

I can’t use a web timer as it seems to cause WebPopupMenu to flash on some browsers.

Use a server-side timer instead of the WebTimer, if you have a PopupMenu on the same page.

Drag a standard object from the Library to the WebPage, and make it’s super “Timer”. Then use as usual.

[quote=295572:@Michel Bujardet]Use a server-side timer instead of the WebTimer, if you have a PopupMenu on the same page.

Drag a standard object from the Library to the WebPage, and make it’s super “Timer”. Then use as usual.[/quote]

Are you suggesting I drag a “Generic Object” onto the page and change it’s super to Timer.

Does this then have access to the session or is it the same as Xojo.Core.Timer.CallLater which fires on the main thread?

Yes, obviously.

All timers, as well as sockets events, require that you use a SessionContext to access the session.

am I not already doing that using Xojo.Core.Timer.CallLater and in the Method I’m calling

[code]Dim Sess As Session = MySession

Dim Context As WebSessionContext

’ Check Session Defined
If Sess <> Nil Then

' Define Context
Context = New WebSessionContext(Sess)

End If[/code]

I advised to use a server-side timer to alleviate the issue with PopupMenu. That’s it. In terms of code in Action, it is just the same.

Thats why I’ve been using Xojo.Core.Timer.CallLater(0, WeakAddressOf LoadDataComplete), instead of a WebTimer. All I use the timer for is checking for the WebThread to finish and create a WebContainer, surly it’s easier to use Xojo.Core.Timer.CallLater at the end of the WebThread?

However the side affect has been that when I try to create a WebContainer it will give randomly me “Exception Message: Control cannot be created because no session context is available.” It’s very hit and miss as to when this happens and I’ve yet to be able to make it happen when running it via the IDE.

Despite me using the following in the method that Xojo.Core.Timer.CallLater uses.

[code]Dim Sess As Session = MySession

Dim x As ContainerControl1

Dim Context As WebSessionContext

’ Check Session Defined
If Sess <> Nil Then

' Define Context
Context = New WebSessionContext(Sess)

' Define Context
x = New ContainerControl1 

End If[/code]

MySession is a property of the WebPage and set during the WebPage open event.

Indeed Timer of Xojo.Core.Timer are both fine.

Indeed I get the same error. Greg may be able to explain why.

Greg did say this, not sure from that it will never work correctly or you need to use WebSessionContext which I’m already doing. Will wait for a reply from Greg who may be able to explain more.

Alright. I think what you experience is because of a bad reference to Session.

A better way to proceed is to store a reference to the session object so you can call it from within the event.

I added a mySession as WebSession property to the Webpage, which I initialize in Open as such :

mySession = Session

This does not trigger the exception, even with a multiple timer that creates dozen of new ContainerControl1 :

[code]Sub Action() Handles Action
Dim context As New WebSessionContext(self.mySession)

dim x as ContainerControl1

x = new ContainerControl1

system.DebugLog x.ControlID
End Sub
[/code]

Just out of curiosity… why not raise an event or call a delegate when the thread finishes?

[quote=295655:@Michel Bujardet]Alright. I think what you experience is because of a bad reference to Session.

A better way to proceed is to store a reference to the session object so you can call it from within the event.

I added a mySession as WebSession property to the Webpage, which I initialize in Open as such :

mySession = Session

This does not trigger the exception, even with a multiple timer that creates dozen of new ContainerControl1 :

[code]Sub Action() Handles Action
Dim context As New WebSessionContext(self.mySession)

dim x as ContainerControl1

x = new ContainerControl1

system.DebugLog x.ControlID
End Sub
[/code][/quote]

Wouldn’t that create a circular reference?

What do you mean ?

The mySession property is merely a pointer to the current Session. It does create a reference, so you may want to nil it in the WebPage close, but I don’t see how it would create a circular reference.

[quote=295662:@Michel Bujardet]What do you mean ?

The mySession property is merely a pointer to the current Session. It does create a reference, so you may want to nil it in the WebPage close, but I don’t see how it would create a circular reference.[/quote]

My understanding was you need to use a computed property like in the bottom half of my first post otherwise you create a circular reference, at least that’s why I read in another thread. Think it was Greg that said it funny enough I’ll see if I can find the thread.

Found it https://forum.xojo.com/18983-why-does-my-session-object-go-away/1

Circular Reference E.g WebPage has a reference to the session and the session has a reference to the WebPage

The other solution is to store the Session.Identifier, and in the timer event, instead of trying to reference session directly as you did before that failed, cycle through all sessions, until you find the same session identifier.

Here :

Public Property mySession as String

[code]Sub Action() Handles Action
Dim context As WebSessionContext

For i As Integer = 0 To App.SessionCount - 1
// Without creating a WebSessionContext here, creating
// the page would fail triggering a SessionNotAvailableException.
If App.SessionAtIndex(i).Identifier = mySession then
context = new WebSessionContext(App.SessionAtIndex(i))
end if
Next

dim x as ContainerControl1

x = new ContainerControl1

system.DebugLog x.ControlID
End Sub
[/code]

Hadn’t thought about using a delegate, I assume the last thing I do in the WebTread is call the delegate?

Yes. Web projects don’t carry the same issue as a desktop project in that you are not prevented from accessing ui from it, so I’d bet you can forego the timer altogether.

WebThreads can manipulate the UI?