That is a good observation. However, in this case the resource being protected by the lock is a static resource, and so the lock must occur at the AppDomain level.
Arguably I could have done this:
private static object _myLock = new object();
...
lock(_myLock)
{
//blah
}
To be slightly more "proper", but the net result is the same as far as I can see.
Having had my morning cup of coffee, the fact is that you can't even use a static field like I said in my previous post, because that would span all instances of any subclass of BusinessBase - which is bad.
What's needed is some per-instance-type object against which the code can lock. The use of this.GetType() is an easy way to get exactly such an object.
But if you can think of a better way to get an object that is common only to all instances of a specific subclass of BusinessBase, then I'm totally open to using such a technique.
Something like a Dictionary<type,object> came to mind - but then there are threading (and overhead) issues with creating/populating/maintaining that Dictionary - so it seems like a very problematic approach.
Also, remember that this lock process occurs only on the very first time the first isntance of a given business object type is created. So anything (like a Dictionary) that involves consuming memory over the lifetime of the AppDomain is a bad solution - because that memory would be wasted - no code would ever access the value after that one, first hit.
Maybe, just maybe, something like this would work. In BusinessBase:
protected abstract object GetSyncRoot();
Then in every subclass you'd have to implement that method like this:
private static object _syncRoot = new object();
protected override object GetSyncRoot()
{
return _syncRoot;
}
Of course this would instantly break every object in every application where CSLA is used, and so it is a very poor solution too...
Yes, that would work. But I agree that it would likely never
been overridden, so I think I won’t change anything at this point.
If someone comes along with an actual deadlock issue that
requires a solution, I may make such a change at that time.
Rocky
From: Jason Gerard
[mailto:cslanet@lhotka.net]
Sent: Monday, March 05, 2007 10:08 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Potential Deadlock
You could define GetSyncRoot() in the base like so
protected virtual object GetSyncRoot()
{
return this.GetType();
}
and update the Constructor to use it.
Then specify in the book, comments, everywhere that you should override with
with an instance type lock.
Seems a bit of a hack though that would never get overriden.
I discuss this briefly in the CSLA .NET Version 2.1 Handbook as well, but the short of it is that the first time an object of any given type is created, its validation and authorization rules are added to a static/Shared list.
If the first creation of that type happened in two objects of the same type at the same time on different threads in the same AppDomain, then you could end up with both objects adding the same information to the same static/Shared lists. The result would be double entries at best, a crash at worst.
The locking is used to avoid that scenario.
Copyright (c) Marimer LLC