ASP.NET lock() doesn't work - asp.net

i try to put a lock to a static string object to access to cache,, the lock() block executes in my local,but whenever i deploy it to the server, it locks forever. i write every single step to event log to see the process and lock(object) just causes the deadlock on the server. The command right after lock() is never executed as the i dont see an entry in the event log.
below is the code:
public static string CacheSyncObject = "CacheSync";
public static DataView GetUsers()
{
DataTable dtUsers = null;
if (HttpContext.Current.Cache["dtUsers"] != null)
{
Global.eventLogger.Write(String.Format("GetUsers() cache hit: {0}",dtUsers.Rows.Count));
return (HttpContext.Current.Cache["dtUsers"] as DataTable).Copy().DefaultView;
}
Global.eventLogger.Write("GetUsers() cache miss");
lock (CacheSyncObject)
{
Global.eventLogger.Write("GetUsers() locked SyncObject");
if (HttpContext.Current.Cache["dtUsers"] != null)
{
Global.eventLogger.Write("GetUsers() opps, another thread filled the cache, release lock");
return (HttpContext.Current.Cache["dtUsers"] as DataTable).Copy().DefaultView;
}
Global.eventLogger.Write("GetUsers() locked SyncObject"); ==> this is never written to the log, so which means to me that, lock() never executes.

You're locking on a string, which is a generally bad idea in .NET due to interning. The .NET runtime actually stores all identical literal strings only once, so you have little control over who sees a specific string.
I'm not sure how the ASP.NET runtime handles this, but the regular .NET runtime actually uses interning for the entire process which means that interned strings are shared even between different AppDomains. Thus you could be deadlocking between different instances of you method.

What happens if you use:
public static object CacheSyncObject = new object();

Related

ASP.NET Object Caching in a Class

I'm trying to create a Caching Class to cache some objects from my pages. The purpose is to use the Caching system of the ASP.NET framework but to abstract it to separate class.
It seems that the caching doesn't persist.
Any ideas what I'm doing wrong here? Is it possible at all to cache object out side the Page it self?
EDIT: added the code:
Insert to cache
Cache c = new Cache();
c.Insert(userid.ToString(), DateTime.Now.AddSeconds(length), null, DateTime.Now.AddSeconds(length), Cache.NoSlidingExpiration,CacheItemPriority.High,null);
Get from the cache
DateTime expDeath = (DateTime)c.Get(userid.ToString())
I get null on the c.Get, even after I did have the key.
The code is in a different class than the page itself (the page uses it)
Thanks.
There are numerous ways you can store objects in ASP.NET
Page-level items -> Properties/Fields on the page which can live for the lifetime of the page lifecycle in the request.
ViewState -> Store items in serialised Base64 format which is persisted through requests using PostBack. Controls (including the page itself - it is a control) can preserve their previous state by loading it from ViewState. This gives the idea of ASP.NET pages as stateful.
HttpContext.Items -> A dictionary of items to store for the lifetime of the request.
Session -> Provides caching over multiple requests through session. The session cache mechanism actually supports multiple different modes.
InProc - Items are stored by the current process, which means should the process terminate/recycle, the session data is lost.
SqlServer - Items are serialised and stored in a SQL server database. Items must be serialisable.
StateServer - Items are serialised and stored in a separate process, the StateServer process. As with SqlServer, items must be serialisable.
Runtime - Items stored in the runtime cache will remain for the lifetime of the current application. Should the applciation get recycled/stop, the items will be lost.
What type of data are you trying to store, and how do you believe it must be persisted?
Right at the beginning of last year I wrote a blog post on a caching framework I had been writing, which allows me to do stuff like:
// Get the user.
public IUser GetUser(string username)
{
// Check the cache to find the appropriate user, if the user hasn't been loaded
// then call GetUserInternal to load the user and store in the cache for future requests.
return Cache<IUser>.Fetch(username, GetUserInternal);
}
// Get the actual implementation of the user.
private IUser GetUserInternal(string username)
{
return new User(username);
}
That was nearly a year ago, and it has been evolved a bit since then, you can read my blog post about it, let me know if thats of any use.
Your cache reference needs to be accessible to all items in your code - the same reference.
If you are newing up the Cache class every time, you are doing it wrong.
I have done almost the same things, but with a different code (and it work for me) :
(CacheKeys is an enum)
using System;
using System.Configuration;
using System.Web;
using System.IO;
public static void SetCacheValue<T>(CacheKeys key, T value)
{
RemoveCacheItem(key);
HttpRuntime.Cache.Insert(key.ToString(), value, null,
DateTime.UtcNow.AddYears(1),
System.Web.Caching.Cache.NoSlidingExpiration);
}
public static void SetCacheValue<T>(CacheKeys key, T value, DateTime expiration)
{
HttpRuntime.Cache.Insert(key.ToString(), value, null,
expiration,
System.Web.Caching.Cache.NoSlidingExpiration);
}
public static void SetCacheValue<T>(CacheKeys key, T value, TimeSpan slidingExpiration)
{
HttpRuntime.Cache.Insert(key.ToString(), value, null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
slidingExpiration);
}
public static T GetCacheValue<T>(CacheKeys key)
{
try
{
T value = (T)HttpRuntime.Cache.Get(key.ToString());
if (value == null)
return default(T);
else
return value;
}
catch (NullReferenceException)
{
return default(T);
}
}

Abstracting HttpContext Request and Session - thread safety

I have the following assemblies in my ASP.NET app:
Website - this is an ASP.NET website
ClassLib - this is just a class lib that contains all the business logic
Class Lib needs to interact with the HttpContext Session and Request objects. This is a code upgrade from an old ASP app, where I've hoovered all the VBScript that contained the logic and put it into VB.NET. We simply didn't have time to rewrite.
Instead of ClassLib interacting directly with HttpContext, which I thought was BAD and also prevented us from unit testing, I introduced the following abstraction layer:
Public Class Request
Private Shared _requestWrapper as IRequestWrapper
Public Shared ReadOnly Property RequestWrapper()
Get
If _requestWrapper Is Nothing Then
Throw New Exception("_requestWrapper is null. Make sure InitRequest() is called with valid parameters")
End If
Return _requestWrapper
End Get
End Property
Public Shared Sub InitRequest(ByRef requestWrapper As IRequestWrapper)
_requestWrapper = requestWrapper
End Sub
Public Shared Function GetVal(ByVal key As String) As Object
Return RequestWrapper.GetVal(key)
End Function
etc.
This means in the unit tests I can supply my own MockRequest object into this Request class, which is just a simple NameValue collection. The code in the ClassLib and the Website then simply use the Request class and are none the wiser that it isn't coming from the HttpContext, but rather this mock class.
When it comes to the real deal, I simply have the following (C#) class:
public class RealRequest : IRequestWrapper
{
public void Initialize(HttpContext context)
{
}
#region Implementation of IRequestWrapper
public object GetVal(string index)
{
return HttpContext.Current.Request[index];
}
etc.
This is initialised in Session_Start of global.asax in the Website, as follows:
protected void Session_Start(object sender, EventArgs e)
{
IRequestWrapper requestWrapper = new RealRequest();
WebSession.Request.InitRequest(ref requestWrapper);
}
I think this is similar to the Static Gateway pattern.
Now, I am aware of singletons and static vars in a multi threaded environment such as ASP.NET, but this is slightly different. When it gets down to the RequestWrapper.GetVal(), its actually going to the HttpContext for that running thread - and pulling the value from that.
Certainly, any concurrent tests that we do with multiple users hitting the same server have never shown up any strange behaviour.
I'm just looking for re-assurance that this is a sound design, and if not why not?
Thanks
Duncan
This is fine. We have a very similar case in our applications that either uses HttpContext if it exists or fake implementations otherwise.
The one thing to watch out for is that there is a very specific instance where HttpContext.Current will return a value but HttpContext.Current.Request will throw an exception when triggered by the Application_Start event. In framework code, you really don't know (or want to know) what triggered the call though.
Workaround for HttpContext.HideRequestResponse being internal? Detect if HttpContext.Request is really available?

Access SQLite from different processes

I'm developing an application that uses SQLite as the primary data storage method. I have two processes running for my app using an alternate entry point.
I need to access the same DB from the two different processes but as we all now SQLite is not like a server DB engine, it can only be accessed once at a time.
I wanted to know if there is a way to kind of "lock" the DB when it's being accessed by other process so that if the second process tries to acces the DB at the same time, it would wait until the first process finishes and then try to access it again.
How can this issue be treated?
If you have not already, create a class that abstracts your database access out and store it in the RuntimeStore. From wherever you are going to interface with SQLite, get a reference to that class using the GUID you stored it with (RuntimeStore.get(long)) and synchronize the class however you would normally (member object lock, synchronized methods).
Do NOT just use the Wikipedia style singleton pattern as it is not a true singleton across processes on this platform.
See:
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/RuntimeStore.html
Sample:
class SQLManager {
private static long GUID = 0xa178d3ce564cae69L; // hash of com.stackoverflow.SQLManager
private SQLManager() {
// ctor stuff here
}
public static SQLManager getInstance() {
RuntimeStore rs = RuntimeStore.getRuntimeStore();
SQLManager instance = rs.get(GUID);
if (instance == null) {
instance = new SQLManager();
rs.put(GUID, instance);
}
return instance;
}
}
You're still using the singleton "pattern" per se, but you're storing the object instance in the RuntimeStore on first getInstance call, and subsequently pulling it form the RuntimeStore - using a GUID that you specify.

Why does my ASP.Net static function's "context" crossover between user sessions?

I think I need some help understanding how static objects persist in an ASP.Net application. I have this scenario:
someFile.cs in a class library:
public delegate void CustomFunction();
public static class A {
public static CustomFunction Func = null;
}
someOtherFile.cs in a class library:
public class Q {
public Q() {
if (A.Func != null) {
A.Func();
}
}
}
Some ASP.Net page:
Page_Init {
A.Func = MyFunc;
}
public void MyFunc() {
System.IO.File.AppendAllText(
"mydebug.txt", DateTime.Now.ToString("hh/mm/ss.fff", Session.SessionID));
}
Page_Load {
Q myQ = new Q();
System.Threading.Thread.Sleep(20000);
mQ = new Q();
}
The idea is that I have a business object which does some operation based on a callback function at the UI level. I set the callback function to a static variable on Page_Init (in the real code version, in the Master page, if that makes a difference). I thought that every execution of the page, no matter what user session it came from, would go through that function's logic but operate on its own set of data. What seems to be happening instead is a concurrency issue.
If I run one user session, then while it is sleeping between calls to that callback function, start another user session, when the first session comes back from sleeping it picks up the session ID from the second user session. How can this be possible?
Output of mydebug.txt:
01/01/01.000 abababababab (session #1, first call)
01/01/05.000 cdcdcdcdcdcd (session #2, first call - started 5 seconds after session #1)
01/01/21.000 cdcdcdcdcdcd (session #1 returns after the wait but has assumed the function context from session #2!!!!!)
01/01/25.000 cdcdcdcdcdcd (session #2 returns with its own context)
Why is the function's context (meaning, its local data, etc.) being overwritten from one user session to another?
Each request to an asp.net site comes in and is processed on it's own thread. But each of those threads belong to the same application. That means anything you mark as static is shared across all requests, and therefore also all sessions and users.
In this case, the MyFunc function that's part of your page class is copied over top of the static Func member in A with every page_init, and so every time any user does a page_init, he's replacing the A.Func used by all requests.
Static data is shared among the entire application domain of your webapp.
In short, it's shared among all the threads serving requests in your webapp, it's not bound to a session/thread/user in any way but to the webapp as a whole.(unlike e.g. php where each request lives in its own isolated environment bar a few knobs provided - such as the session variable.)
I won't try to improve on the other answers' explanations of static members, but do want to point out another way to code around your immediate problem.
As a solution, you could make an instance-oriented version of your class A, store it in a page-level variable, and pass it to Q's constructor on page load:
public class MyPage: Page {
private A2 _a2;
// I've modified A2's constructor here to accept the function
protected Page_Init() { this._a2 = new A2(MyFunc); }
protected Page_Load() {
Q myQ = new Q(this._a2);
// etc..
}
}
In fact, if there's no pressing need to declare A2 earlier, you could just instantiate it when you create your instance of Q in Page_Load.
Edit: to answer the question you raised in other comments, the reason the variables are being shared is that the requests are sharing the same delegate, which has only a single copy of its variables. See Jon Skeet's The Beauty of Closures for more details.
One solution you might consider is using [ThreadStatic].
http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(VS.71).aspx
It will make your statics per thread. There are cavaets however so you should test.
If you want the data to persist only for the current request, use HttpContext.Items:
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.items.aspx
If you want the data to persist for the current user's session (assuming you have session state enabled), use HttpContext.Session:
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.session.aspx

ASP.NET/Static class Race Condition?

I have an ASP.NET application with a lot of dynamic content. The content is the same for all users belonging to a particular client. To reduce the number of database hits required per request, I decided to cache client-level data. I created a static class ("ClientCache") to hold the data.
The most-often used method of the class is by far "GetClientData", which brings back a ClientData object containing all stored data for a particular client. ClientData is loaded lazily, though: if the requested client data is already cached, the caller gets the cached data; otherwise, the data is fetched, added to the cache and then returned to the caller.
Eventually I started getting intermittent crashes in the the GetClientData method on the line where the ClientData object is added to the cache. Here's the method body:
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
ClientData client;
if (_clients.ContainsKey(fk_client))
{
client = _clients[fk_client];
}
else
{
client = new ClientData(fk_client);
_clients.Add(fk_client, client);
}
return client;
}
The exception text is always something like "An object with the same key already exists."
Of course, I tried to write the code so that it just wasn't possible to add a client to the cache if it already existed.
At this point, I'm suspecting that I've got a race condition and the method is being executed twice concurrently, which could explain how the code would crash. What I'm confused about, though, is how the method could be executed twice concurrently at all. As far as I know, any ASP.NET application only ever fields one request at a time (that's why we can use HttpContext.Current).
So, is this bug likely a race condition that will require putting locks in critical sections? Or am I missing a more obvious bug?
If an ASP.NET application only handles one request at a time all ASP.NET sites would be in serious trouble. ASP.NET can process dozens at a time (typically 25 per CPU core).
You should use ASP.NET Cache instead of using your own dictionary to store your object. Operations on the cache are thread-safe.
Note you need to be sure that read operation on the object you store in the cache are threadsafe, unfortunately most .NET class simply state the instance members aren't thread-safe without trying to point any that may be.
Edit:
A comment to this answer states:-
Only atomic operations on the cache are thread safe. If you do something like check
if a key exists and then add it, that is NOT thread safe and can cause the item to
overwritten.
Its worth pointing out that if we feel we need to make such an operation atomic then the cache is probably not the right place for the resource.
I have quite a bit of code that does exactly as the comment describes. However the resource being stored will be the same in both places. Hence if an existing item on rare occasions gets overwritten the only the cost is that one thread unnecessarily generated a resource. The cost of this rare event is much less than the cost of trying to make the operation atomic every time an attempt to access it is made.
This is very easy to fix:
private _clientsLock = new Object();
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
lock (_clientsLock)
// Check again because another thread could have created a new
// dictionary in-between the lock and this check
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
if (_clients.ContainsKey(fk_client))
// Don't need a lock here UNLESS there are also deletes. If there are
// deletes, then a lock like the one below (in the else) is necessary
return _clients[fk_client];
else
{
ClientData client = new ClientData(fk_client);
lock (_clientsLock)
// Again, check again because another thread could have added this
// this ClientData between the last ContainsKey check and this add
if (!clients.ContainsKey(fk_client))
_clients.Add(fk_client, client);
return client;
}
}
Keep in mind that whenever you mess with static classes, you have the potential for thread synchronization problems. If there's a static class-level list of some kind (in this case, _clients, the Dictionary object), there's DEFINITELY going to be thread synchronization issues to deal with.
Your code really does assume only one thread is in the function at a time.
This just simply won't be true in ASP.NET
If you insist on doing it this way, use a static semaphore to lock the area around this class.
you need thread safe & minimize lock.
see Double-checked locking (http://en.wikipedia.org/wiki/Double-checked_locking)
write simply with TryGetValue.
public static object lockClientsSingleton = new object();
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null) {
lock( lockClientsSingleton ) {
if( _clients==null ) {
_clients = new Dictionary``();
}
}
}
ClientData client;
if( !_clients.TryGetValue( fk_client, out client ) )
{
lock(_clients)
{
if( !_clients.TryGetValue( fk_client, out client ) )
{
client = new ClientData(fk_client)
_clients.Add( fk_client, client );
}
}
}
return client;
}

Resources