Hi,
Because of a strange behavior of my application I would need a clarification about the definition of shared variable and method. The scenario is as follows.
I created a library for managing queries on Mysql.
To populate a datatble I have defined the following shared method:
Public Shared Function FillDataTable (ByVal cnnstr As String, ByRef Qry As String) As DataTable.
In my application I defined the public variable:
Public dttGRN As New DataTable, which I have populated like this.
dttGRN = ASNetL.Common.DataBase.MySql.FillDataTable (MsqCnnStr, qry). MsqCnnStr is the connction string and qry is the query.
Up to here everything works.
The question is as follows.
If I have two open sessions, it is possible that the dttGRN variable is shared between the two sessions due to the fact that the FillDataTable method is defined as a shared? I ask this question because from the debugging of my application it seems (but I have to make further inquiries) that the content of dttGRN a session changes when it changes on the other session.
I hope I was clear enough and thanks in advance.
Converting statics into session-statics is one of the first steps we do in our migration projects.
These are 3 solutions, from easier to faster.
Assuming you have:
Module Module1 Public Name As String End Module Public Class Class1 Public Sub Test() Module1.Name = "Test" End Sub End Class
Change it to:
Module Module1 Public Property Name As String Get Return Wisej.Web.Application.Session("Name") End Get Set(value As String) Wisej.Web.Application.Session("Name") = value End Set End Property End Module
The code using Module1.Name is unchanged, Name is still shared, but it returns/gets the value from the current session.
If you have many module shared this is not a good solution and the name in the session may conflict with other code using the session storage. So you may want to prefix the key with something. It may also be slow if you use the property many times in a request.
A better approach is to convert all shared into class variables and store the entire instance as a singleton in the session:
Module Module1 Public ReadOnly Property Statics As StaticsWrapper Get Dim key As String = GetType(StaticsWrapper).FullName Dim instance As StaticsWrapper = Wisej.Web.Application.Session(key) If (instance Is Nothing) Then instance = New StaticsWrapper Wisej.Web.Application.Session(key) = instance End If Return instance End Get End Property Public Class StaticsWrapper Public Name As String End Class End Module
The code using Module1.Name should become Module1.Statics.Name. The advantage is that you can put many fields in StaticsWrapper and save/load only 1 instance from the session.
This last one is the same StaticsWrapper approach but it’s faster. It uses a thread static to retrieve the session static instance only once on first use.
Module Module1 Sub New() AddHandler Wisej.Web.Application.ThreadBegin, AddressOf Module1_ThreadCleanUp AddHandler Wisej.Web.Application.ThreadEnd, AddressOf Module1_ThreadCleanUp End Sub <ThreadStatic> Private StaticsInstance As StaticsWrapper Private Sub Module1_ThreadCleanUp(sender As Object, e As EventArgs) StaticsInstance = Nothing End Sub Public ReadOnly Property Statics As StaticsWrapper Get If StaticsInstance Is Nothing Then Dim key As String = GetType(StaticsWrapper).FullName StaticsInstance = Wisej.Web.Application.Session(key) If (StaticsInstance Is Nothing) Then StaticsInstance = New StaticsWrapper Wisej.Web.Application.Session(key) = StaticsInstance End If End If Return StaticsInstance End Get End Property Public Class StaticsWrapper Public Name As String End Class End Module
The code using Module1.Name should become Module1.Statics.Name.
Wisej.Web.Application has two events ThreadBegin and ThreadEnd that can be used to clean up the thread static when a thread starts and ends. Every request is on a new thread but the threads are reused since they come from the thread pool. That’s why we have the ThreadBegin and ThreadEnd events – to let an app (usually extensions or special implementations) manage thread statics effectively.
HTH
BTW, I didn’t test any of the code above, I tried to convert it from C#. In any case, I’m sure you get the gist of the approach and can adapt it to your app.
Luca,
Thank you very much for your suggestions.
I used the third solution and it seems to work perfectly
Thanks for the clarification.
In fact, I have defined at the module level the data structures that should be instantiated in a univocal way for each session. I think therefore that I will have to work with the session object.
At this point I make a consideration (due to my experience on windows form and not on web based applications):
Is it possible to declare a class visible in the whole project (public) but unique for each session ?.
From what I understand if I have the “ClsAccount” class, I can not use a module to declare:
module GlobalData
Public Acc as new ClsAccount
end module
as this causes the variation of its content on all open sessions each time a new session is opened and changes its values.
A function canno change the declaration of a variable passed to the function.
Module variables are implicitly shared in VB.NET.
https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/shared
Very curious about this myself. I use a similar structure (VB module with shared function) to access the database and wonder about multi-session contamination.
‘gets a single database value with a query and database name
Shared Function GetDBValue(ByVal strQuery As String, ByVal strDatabaseName As String) As String
Dim strReturnValue As String = “”
Using connn As New MySqlConnection(northvineweb)
Using myCommand As New MySqlCommand(strQuery, connn)
connn.Open()
Dim MyReader As MySqlDataReader
MyReader = myCommand.ExecuteReader
While MyReader.Read()
strReturnValue = MyReader.GetValue(0).ToString
End While
Return strReturnValue
End Using
End Using
End Function
Please login first to submit.