[SOLVED] Shared Variables and methods

Answered
1
1

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.

  • You must to post comments
Best Answer
0
0

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.

 

  • You must to post comments
0
0

Luca,
Thank you very much for your suggestions.
I used the third solution and it seems to work perfectly

  • You must to post comments
0
0

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.

 

  • You must to post comments
0
0

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

  • You must to post comments
0
0

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

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.