I made a two static classes
NotInheritable Class gObject2
Public Shared TestSyncLock As String = "test"
End Class
NotInheritable Class gObject3
Public Shared TestSyncLock As String = "test"
End Class
Then I have two aspx
Synclock1.aspx:
Public Class SyncLock1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SyncLock gObject2.TestSyncLock
Thread.Sleep(10000)
End SyncLock
End Sub
End Class
Synclock2.aspx
Public Class SyncLock2
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SyncLock gObject3.TestSyncLock
SomeDiv.InnerHtml = "It works"
End SyncLock
End Sub
End Class
When I go to synclock1.aspx it spins for 10 seconds and shows a blank page as expected.
When I go to synclock2.aspx it spits out it works
Everything is good so far.
Now when I go to synclock1.apx and then in another browser got to synclock2.aspx, synclock2.aspx doesn't finish loading until synclock1.aspx finishes.
These are 2 different objects I'm locking with synclock, but it treats them the same. Why is this?
The SyncLockstatement takes an object reference as its argument. As the String type is a reference type, your code is satisfying that constraint. However, due to String Interning in .Net, the literal value equality of the two separate String references is also causing referential equality between gObject2.TestSyncLock and gObject3.TestSyncLock.
From: String.IsInterned Method - Remarks (emphasis added)
The common language runtime automatically maintains a table, called
the intern pool, which contains a single instance of each unique
literal string constant declared in a program, as well as any unique
instance of String you add programmatically by calling the Intern
method.
The intern pool conserves string storage. If you assign a literal
string constant to several variables, each variable is set to
reference the same constant in the intern pool instead of referencing
several different instances of String that have identical values.
Since both gObject2.TestSyncLock and gObject3.TestSyncLock are pointing to the same String reference, SyncLock gObject2.TestSyncLock will block SyncLock gObject3.TestSyncLock.
The subject code is a good example of how string interning can cause unexpected behavior. The article Interning Strings and immutability provides additional details on the mechanics of interning and also provides another example where interning can cause unexpected results.
So the moral of this story is to avoid using strings as the argument for SyncLock. It is safer to use something like the following:
NotInheritable Class gObject2
Public Shared TestSyncLock As New Object
End Class
NotInheritable Class gObject3
Public Shared TestSyncLock As New Object
End Class
Related
As I'm self taught my VB coding is not bad but my use of OOP is poor. I'm sure this can be done but I have not found out how yet.
I am building a webforms app which needs to grab data about a user from AD. I have a Person Class which I can use as follows
Public Class _Default
Inherits System.Web.UI.Page
Dim LoggedOnPerson As Person 'Added here so available throughout class
Private strLoggedOnUser As String
Private strADDomain As String
Private strADUserID As String
Public Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
strLoggedOnUser = Request.ServerVariables("LOGON_USER").ToUpper
strADDomain = strLoggedOnUser.Split("\")(0)
strADUserID = strLoggedOnUser.Split("\")(1)
If Not IsPostBack Then
'Dim LoggedOnPerson As Person *** changed to
LoggedOnPerson = New Person
'Get details from AD for logged on user
LoggedOnPerson.GetDetails(strADDomain, strADUserID)
'Store in Session
Session("LoggedOnUser") = LoggedOnUser
'This will now give me access to details such as
'LoggedOnPerson.EmailAddress
'LoggedOnPerson.GivenName
'LoggedOnPerson.TelephoneNo etc.
Else
'Postback so pull in details from Session
LoggedOnUser = Session("LoggedOnUser")
End If
End Sub
End Class
My problem is that I cannot access LoggedOnPerson in other events. e.g.
Public Sub SaveDetails()
Dim email As String = LoggedOnPerson.Email
'This now produces correct result. No error that LoggedOnPerson is not declared
End Sub
I of course get LoggedOnPerson is not declared error. How can I get around this.
You have created the object of "Person" inside Page_Load event. Take it outside and declare at the class level. Also add that object to view state/session state on Page_Load event and typecast it to "Person" class inside other events.
I'm now work on ASP.NET project
and want to use Page.Cache property to cache the String data like bellow way.
but, it behaves like having a Session scope.
I understand Page.Cache property is retuning a current System.Caching.Cache object
and that must have an Application scope.
I could check below code works fine, but my project's code not -- it makes cache for per session.
And, that replaced Cache of Application (with Lock and UnLock) works fine too.
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim key_str As String = "cache_key"
Dim cached_value = Cache.Get(key_str)
If cached_value Is Nothing Then
cached_value = "stored_value"
Cache.Insert(key_str, cached_value, Nothing, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5), CacheItemPriority.Normal, New CacheItemRemovedCallback(AddressOf RemovedCallback))
End If
Label1.Text = cached_value
End Sub
Public Sub RemovedCallback(ByVal key As String, ByVal value As Object, ByVal removedReason As CacheItemRemovedReason)
Debug.WriteLine("#Callback!")
End Sub
End Class
above code
works fine
my project code
works like session scope
and If replaced Cache with Application, that works fine
Are there any possible to occur such a behavior or not?
(or I just made a mistake on anywhere else in logics?)
Please point out If concerning some configure files.
I maybe made a mistake.
My project is a Azure project and so Page.Cache is to store a data for per azure instance? Right?
When are Shared (Static) variables created and destroyed. For example have a look at the code below:
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Person.testCon = New SqlConnection
Person.Age = 30
Dim p1 As Person
End Sub
End Class
Imports System.Data.SqlClient
Public Class Person
Public Shared testCon As SQLConnection
End Class
The testCon variable is accessible from the Form_Load before the first instance of Person is created. I realise that it is probably not good practice to have a connection as a shared variable but I want to get my point across. I also want to know when variables are created and destroyed if they are primitives (like Person.Age in the example)
Shared variables live for the length of your application, according to Microsoft.
However, object type variables are only instantiated when you tell them to be.
You can verify this behavior by creating a new test class:
Public Class Class1
Sub New()
System.Diagnostics.Debug.Fail("Class Created")
End Sub
End Class
Then create a shared variable for this class as a member variable in another class:
Private Shared m_TestClass As Class1
If you don't access the shared variable, the Debug.Fail statement will not be executed. However, as soon you instantiate this class and assign it, it will be fired (just like any other object):
m_TestClass = New Class1
Shared variables live until the AppDomain they reside in is unloaded.
You could also test this by adding a Finalize statement to the test class with a similar Debug.Fail statement.
The lifetime is one reason that you should use SyncLock when assigning new values to object-type shared variables.
I have a database "Pubs" with a table "authors". I have made a dbml file from the database by dragging over "authors".
Here is the "Default.aspx.vb"
Public Class _Default
Inherits System.Web.UI.Page
Dim author As Object
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim db As New PubsContext
Dim authors = From p In dbo.authors _
Select p
GridView1.DataSource = author
GridView1.DataBind()
End Sub
End Class
Here is the class for it: "Class1.vb"
Partial Public Class PubsContext
Dim authors As Object
Public Function GetProductsByCategory(ByVal id1 As Integer) As IEnumerable(Of authors)
Return From p In Me.authors _
Where p.au_id = id1 _
Select p
End Function
End Class
Error code:
"Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ".
In references there is already a "System.Data.Linq". What should I do?
Well this is the problem:
Dim authors As Object
That's just an object. What does it mean to call Select, Where etc on that? Where are you even giving it a value? Work out what the type should really be, make sure you give it an appropriate value to start with, and you should be fine.
It's not clear why you're introducing your own authors field at all, to be honest - I'd expect the generated context to have an Authors property of type Table<Author> or something similar.
(I note that you're also trying to set GridView1.DataSource to author rather than authors, by the way... Why are you doing that? What value are you expecting the author field in _Default to have?)
I have been researching this one for awhile. I found several resources on the subject and they all tend to use the same approach - override Page.Render, use the HtmlTextWriter to convert the output into a string, and then use a series of compiled regular expressions to remove the extra whitespace. Here is an example.
Well, I tried it and it works...but....
In Safari 5.0, this seems to cause all sorts of performance issues with loading images and getting "server too busy" errors. IE 7, FireFox 3.6 and Google Chrome 6.0 seem to work okay, but I haven't stress tested the server very much. Occasionally there seems to be lags in the time the page is generated, but once the html is sent to the browser, the page displays quickly.
Anyway, when you think about it, it seems rather silly to have .NET build up all of these tabs and line breaks only to strip them all out again using string parsing - the least efficient way to strip them out. It would make more sense to override the HtmlTextWriter and pass it into the tree on the main page request in order to avoid putting them into the output at all - logically there should be a performance gain instead of a hit in that case.
Even if I can only remove 50% of the whitespace using this method, it will still leave much less work for the regular expressions to do - meaning it should perform better than it does with regular expressions alone.
I tried using a Control Adapter and overriding several of the members
Directing all calls to WriteLine() to the corresponding Write() method
Setting the NewLine property to an empty string
Overriding the OutputTabs() method and simply removing the code
Overriding the Indent property and returning 0
I also tried overriding RenderChildren, Render, BeginRender, and EndRender to pass in my custom HtmlTextWriter, but I can't seem to make even a simple label control remove the tabs before its tag. I also dug through the framework using Reflector, but I simply can't figure out how these characters are being generated - I thought I was using a "catch all" approach, but apparently I am missing something.
Anyway, here is what I have come up with. This code is not functioning the way I would like it to. Of course, I have also tried overriding the various Render methods on the page directly and passing in an instance of my custom HtmlTextWriter, but that didn't work either.
Public Class PageCompressorControlAdapter
Inherits System.Web.UI.Adapters.ControlAdapter
Protected Overrides Sub RenderChildren(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.RenderChildren(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub BeginRender(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.BeginRender(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub EndRender(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.EndRender(New CompressedHtmlTextWriter(writer))
End Sub
End Class
Public Class CompressedHtmlTextWriter
Inherits HtmlTextWriter
Sub New(ByVal writer As HtmlTextWriter)
MyBase.New(writer, "")
Me.InnerWriter = writer.InnerWriter
Me.NewLine = ""
End Sub
Sub New(ByVal writer As System.IO.TextWriter)
MyBase.New(writer, "")
MyBase.InnerWriter = writer
Me.NewLine = ""
End Sub
Protected Overrides Sub OutputTabs()
'Skip over the tabs
End Sub
Public Overrides Property NewLine() As String
Get
Return ""
End Get
Set(ByVal value As String)
MyBase.NewLine = value
End Set
End Property
Public Overrides Sub WriteLine()
End Sub
Public Overrides Sub WriteLine(ByVal value As Boolean)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Char)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal buffer() As Char)
MyBase.Write(buffer)
End Sub
Public Overrides Sub WriteLine(ByVal buffer() As Char, ByVal index As Integer, ByVal count As Integer)
MyBase.Write(buffer, index, count)
End Sub
Public Overrides Sub WriteLine(ByVal value As Decimal)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Double)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Integer)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Long)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Object)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Single)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal s As String)
MyBase.Write(s)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object)
MyBase.Write(format, arg0)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object)
MyBase.Write(format, arg0, arg1)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object, ByVal arg2 As Object)
MyBase.Write(format, arg0, arg1, arg2)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal ParamArray arg() As Object)
MyBase.Write(format, arg)
End Sub
Public Overrides Sub WriteLine(ByVal value As UInteger)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As ULong)
MyBase.Write(value)
End Sub
End Class
In case you are not familliar with control adapters, simply place the xml below in a .browser file in the ASP.NET App_Browsers folder. You can change the controlType to apply the control adapter to a Label or something else for a smaller scope of a test. If I can get this working, it isn't such a big deal to add all of the controls in my project here if it will be necessary to do so.
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page"
adapterType="PageCompressorControlAdapter"/>
</controlAdapters>
</browser>
</browsers>
Anyway, you would think there would just be a simple configuration setting like VerboseHtml="false" or PreserveHtmlFormatting="false" or something along those lines. If you look at the output from MSN.com, they are using some kind of compression similar to this...and it appears to be very performant.
The solution involved using a modified version of a compresson module I found here:
http://omari-o.blogspot.com/2009/09/aspnet-white-space-cleaning-with-no.html
This solution implements a custom PageParserFilter which is then configured in the web.config file. The beauty of this solution is that it filters the white space at compile time, so at runtime there is no performance hit.
And then thanks to Aristos and diamandiev, I looked for a reasonable way to add compression to the response stream for browsers that support it. I found another open source module that can be used for this here: http://blowery.org/httpcompress/
The performance gain was significant with the combination of the two methods - much more than using one or the other. It seems that browsers render much faster when the tabs are removed from the page.
As for static content, I plan to use the method in this article to compress those files as well (except for images of course, they are already compressed): http://www.lostechies.com/blogs/dahlbyk/archive/2010/01/08/script-to-enable-http-compression-gzip-deflate-in-iis-6.aspx
Final Solution
I have added my final solution to this Gist.