Solved

Static member in a shared function exists on each request

Posted on 2011-09-25
11
257 Views
Last Modified: 2012-05-12
Hi,

A static member of a shared function gets incremented by one after each request. I thought it would start from zero again on each page request.

My code is below...

 
Public Partial Class WebForm9
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        RunIt()
    End Sub

    Private Sub RunIt()
        Dim objMyTestClass As New MyTestClass()
        Response.Write(objMyTestClass.UniqueIdOnPage.ToString)
    End Sub
End Class

Public Class MyTestClass
    Public UniqueIdOnPage As Integer = 0

    Public Sub New()
        UniqueIdOnPage = GetUniqueIDOnPage()
    End Sub

    Public Function GetUniqueIDOnPage() As Integer
        Static intUniqueIdOnPage As Integer = -1
        intUniqueIdOnPage += 1
        Return intUniqueIdOnPage
    End Function
End Class

Open in new window


So on each request the displayed result is one more than the previous. Why does this happen because I thought that even though it is a static member in a shared function, it would still be unique to each thread/request.

Can you explain what is happening in this scenario, and show what the code should look like if I do want the unique value to be remain unique for each page.

Thanks for your time with this.

0
Comment
Question by:MonCapitan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
11 Comments
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 36595434
Are you trying to count the number of hits for each page?
0
 
LVL 40
ID: 36595504
That is the role of a Static member, to keep its value. If you want it to reset to zero, declare it with Dim instead of Static.
0
 

Author Comment

by:MonCapitan
ID: 36595950
Thanks for your replies.

I am trying to preserve a counter of the number of times a business object is instatiated per request, i.e. per page.

So, when a page loads, it instatiates 10 business objects. When the same or different user requests the page, the counter starts at 10, not zero, and on the third request the counter starts at 20 etc. I would like the counter to start at zero per request, i.e., the counter is unique to each request, not across the whole application for any and every user.

I hope that is a little clearer. I am moderate when it comes to oop. Thanks for your continued help.
0
Salesforce Has Never Been Easier

Improve and reinforce salesforce training & adoption using WalkMe's digital adoption platform. Start saving on costly employee training by creating fast intuitive Walk-Thrus for Salesforce. Claim your Free Account Now

 
LVL 40
ID: 36596050
Let start from the start. I saw static in only one place in your code, so I jumped right there for my answer, thinking that you did not know exactly how to call it, because there is neigher a static member, nor a shared function in your code.

We have to be at the same level of understanding on the terminology.

What I see in your code is as static variable intUniqueIdOnPage, a standard (not shared) member UniqueIdOnPage, and a standard (not shared either) method GetUniqueIDOnPage. The member and the method are not shared, otherwise they would be the Shared modifier in their declaration. As it is, nothing is shared in your in your code.

Maybe you are mislead, because in some languages, static means shared. In VB, Static means a variable that keeps its value between calls to the same instance, and Shared means a variable or method that can be called without an instance (directly on the class) but will be shared by different instances.

So, a Static variable is unique for each instance (unless it is part of a shared method, which is not the case here).

A Shared variable would be the same for each instances.

The way you use MyTestClass in RunIt, you instantiate it only once because it gets destroyed at the end of the RunIt method. An instance create with Dim is destroyed when you get out of the method. So, from the code we see here, the value of UniqueIdOnPage should never be greater than zero. In fact, the static is useless, it could have been declared with Dim, since it will be called only once by each instance.

Is this the real code or something you built up as a demo for us? This is never a good thing todo, because when someone do that, more often than not, they remove the cause of the problem from the sample code.

0
 

Author Comment

by:MonCapitan
ID: 36596100
My deepest apologies. Yes you are right, I have shortened this code for demo. However the demo when run is proof of concept; the value increases by one on each request. But, you are right, I have missed out the 'shared' keyword. The code should read...

 
Public Partial Class WebForm9
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        RunIt()
    End Sub

    Private Sub RunIt()
        Dim objMyTestClass As New MyTestClass()
        Response.Write(objMyTestClass.UniqueIdOnPage.ToString)
    End Sub
End Class

Public Class MyTestClass
    Public UniqueIdOnPage As Integer = 0

    Public Sub New()
        UniqueIdOnPage = GetUniqueIDOnPage()
    End Sub

    Public Shared Function GetUniqueIDOnPage() As Integer
        Static intUniqueIdOnPage As Integer = -1
        intUniqueIdOnPage += 1
        Return intUniqueIdOnPage
    End Function
End Class

Open in new window


Notice the Shared keyword on the last increment function. This is probably a game changer and I apologise for missing it out.

My thoughts are that once the request has run the code and delivered the page, the code that runs is disposed of and 'recreated' when run again from the begining but it seems the value of UniqueIDOnPage is preserved between requests and between threads almost as if it is an application variable.

Why is that?
0
 
LVL 40

Accepted Solution

by:
Jacques Bourgeois (James Burger) earned 500 total points
ID: 36596249
OK, here we are.

A Shared function is shared by all the instances. You can even call it without an instance, with MyTestClass.GetUniqueIDOnPage.

So, the function being shared by all instances, and intUniqueIdOnPage being static, the variable is also shared by all the instances. Thus your problem.

So we have to rethink the way to do it. Unfortunately, it does not jump at me. I have a feeling that it won't be too hard, but I have to think of it with a clearer mind. Had just a bit too much wine tonight.

Let me sit on it. I hope you are not in a hurry, I will be in a rush for a couple of days. But as soon as I have a few minutes, I'll find something.

Maybe somebody will also come with something in between.

0
 

Author Comment

by:MonCapitan
ID: 36597460
I appreciate the response. Yeh red wine makes me think awesome things for around 45 minutes then it gets muggy from then on.

Well, the way I have done it is working exactly as I want it to work. The problem is that I don't know why intUniqueIdOnPage stays live for multiple Users and across multiple requests and just keeps incrementing.

Create a web page with the code above and you will see.

Any more thoughts would be greatly appreciated.
0
 

Author Comment

by:MonCapitan
ID: 36597469
...basically, it is like it isn't threadsafe?
0
 
LVL 40
ID: 36599419
I have seen a piece of information that had not catch me before. So here what I see.

From my experience in object programming, I could tell you that a static variable in a shared method will be shared by all instances. This is the whole point of Shared. Usually, this is at the application level.

Now, the new information i got is shared by all users.

I don't do ASP, so I do not know how to handle this, but I think I know the cause. I understand that theres is a caching mechanism in ASP that enables you to cache a page on the server so that it does not have to be recreated on each call. There is also something of that type for dlls if I am not mislead. In such a case, all the users are using the same copy of your class. In such a case, the static variable is the same for everybody.

Depending on the application needs, and on the number of users, you might be able to prevent your class from being cached and have one copy for each individual user/session. We have that possibility in remoting (singleton vs single call), so they probably implemented something like that in ASP as well. But with my very limited experience in ASP, I can't tell for sure.

From all that, what you want to do won't be easy, as it is too often the case in ASP (that is why I will stick to Windows applications as long as there will be enough customers that have needs for them).

The only way I see you implementing your counter is not trough a single integer variable. You need a class that will record the page and the count if you have one copy of you class dll for each user, add the session if you work from a cached copy. Let's assume the last one: session/page/count

In you class you will handle a Shared collection of these objects. On each instantiation, you will first look through the collection to see if there is already an entry in the collection for the combination session/page. If not, you create a new object and add it to the collection. If there was already one, you simply increment the count. This way, you will have an individual counter for each session/page.

Naturally, you will need to have some mechanisme to clean up the unneeded entries in the collection for the sessions that are no longer active.

That's the best I can offer. Maybe somebody knows of something else specific to ASP that might be simpler.

0
 

Author Comment

by:MonCapitan
ID: 36895738
Thanks for the reply and effort.

I have done much reading and have found thatin vb.net, a static member in a shared function is available across many requests and is like variable at the application level. It only resets when the application is recycled (or something to that effect).

I have refactored my code to use a different approach to the code exampled above.

Thank you for taking the time to try and answer my query.
0
 

Author Closing Comment

by:MonCapitan
ID: 36895741
The question was not answered but the feedback pointed me in the right direction.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question