I've got a generic cache access method inside a singleton class that takes three parameters.
a delegate (void return type with no parameters)
a cache label
a lock object designed to stop concurrent cache setting
See below:
protected delegate T GetDataMethod<T>();
protected override D GetCachedData<D>(GetDataMethod<D> dataAccessMethod, string cachelabel, object lockObject)
{
if (MemoryCache.Default[cachelabel] == null)
{
lock (lockObject)
{
//Inside the lock, test once again in case the cache object has been set already
if (MemoryCache.Default[cachelabel] == null)
{
umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -10, cachelabel + " inside lock, cache empty");
D data = default(D);
try
{
data = dataAccessMethod();
}
catch (Exception ex)
{
//Logging
}
MemoryCache.Default.Add(cachelabel, data, GetCacheItemPolicy());
}
}
}
return (D)MemoryCache.Default[cachelabel];
}
I've got separate lock objects for each of the data collections that get cached set as static readonly objects. However, by passing them to the method their scope only exists within the method so the lock becomes irrelevant.
I can't use 'ref' as you can't pass a static object by ref, given that the surrounding class is a singleton, will it matter if I make the lock objects non static? If it will, can anyone recommend a better way of handling it without using a switch statement based on the cacheLabel?
EDIT:
Just for clarity the method footprint:
protected override D GetCachedData<D>(GetDataMethod<D> dataAccessMethod, string cachelabel, ref object lockObject)
won't work as the lock objects are static. I guess the question really is - Inside a singleton, do lock objects need to be static to be threadsafe? (Yes, it's a thread safe singleton)
I think you're missing the point of the ref keyword - you don't need it. You're passing an object which is already a reference type. Adding the ref keyword will make it a reference to a reference.
Related
I have a very large project with multiple pages, where each page has many IDisposable members.
I'm trying to figure out a way to dispose all the IDisposable members in a loop so I won't have to type x1.Dispose(); x2.Dispose; ... xn.Dispose on each class.
Is there a way to do this?
Thank you.
Sure, just make sure that you create a list to hold them, and a try finally block to protect yourself from leaking them.
// List for holding your disposable types
var connectionList = new List<IDisposable>();
try
{
// Instantiate your page states, this may be need to be done at a high level
// These additions are over simplified, as there will be nested calls
// building this list, in other words these will more than likely take place in methods
connectionList.Add(x1);
connectionList.Add(x2);
connectionList.Add(x3);
}
finally
{
foreach(IDisposable disposable in connectionList)
{
try
{
disposable.Dispose();
}
catch(Exception Ex)
{
// Log any error? This must be caught in order to prevent
// leaking the disposable resources in the rest of the list
}
}
}
However, this approach is not always ideal. The nature of the nested calls will get complicated and require the call to be so far up in the architecture of your program that you may want to consider just locally handling these resources.
Moreover, this approach critically fails in the scenario where these Disposable resources are intensive and need to be immediately released. While you can do this, i.e. track your Disposable elements and then do it all at once, it is best to try to get the object lifetime as short as possible for managed resources like this.
Whatever you do, ensure not to leak the Disposable resource. If these are connection threads, and they are inactive for some period of time, it may also be wise to simply look at their state and then re-use them in different places instead of letting them hang around.
Using reflection (not tested):
public static void DisposeAllMembersWithReflection(object target)
{
if (target == null) return;
// get all fields, you can change it to GetProperties() or GetMembers()
var fields = target.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
// get all fields that implement IDisposable
var disposables = fields.Where(x => x.FieldType.GetInterfaces().Contains(typeof(IDisposable)));
foreach (var disposableField in disposables)
{
var value = (IDisposable)disposableField.GetValue(target);
if (value != null)
value.Dispose();
}
}
Create method which will dispose all your disposable objects:
public void DisposeAll()
{
x1.Dispose();
x2.Dispose();
x3.Dispose();
. . .
}
and call it wherever you need it.
In the following example, _instance is always resolving to null. How should I be getting the value safely out of the thread?
class GenericThreadManager<TMyClass> where TMyClass : new()
{
private TMyClass _instance;
private object synLock = new object();
private Thread generalThread;
public GenericThreadManager()
{
//wrapped code
lock (this.synLock)
{
generalThread = new Thread(_instance => this._instance = new TMyClass());
generalThread.Start(); // instantiates the object
while (this._instance == null) // allways compares to null even after
// thread completes
{
Thread.Sleep(100);
}
Thread.Sleep(100);
}
//wrapped code
}
Edits based on comments (thank you for the comments)
The while loop after the thread is just to debug / test if the thread is ever completing.
The context – is that this class instantiates an object that takes a long time to build (i.e. loading lots of data) on a thread. This class then governs access to the object until the instantiation is complete. Crudely I was doing this by checking if the object was null.
Although there might be better ways to solve the problem – I would like to understand where I’ve gone wrong in my understanding of threaded code / and Lambda’s.
Crudely – I understood generalThread = new Thread(_instance => this._instance = new TMyClass()); to be setting the threadstart to the Lambda expression:
_instance => this._instance = new TMyClass()
I understand this expression creates a new instance of TMyClass() and place reference to that object in _instance.
I then understood that the threads my not be synchronised, so the value of _instance wouldn’t be reliably set – unless it was set to volatile.
With it set to volatile I get the following compile error:
Error CS0677 'GenericThreadManager<TMyClass>._instance': a volatile field cannot be of the type 'TMyClass'
How do I resolve the above error or synchronise the threads to move the reference to the object to _instance.
# Panagiotis Kanavos could you explain why the each constructor would see a different lock. The GenericThreadManager is making a private instance of TMyClass, a different object, in the GenericThreadManager constructor. It locking on synLock, so in theory, any other methods on GenericThreadManager should block on the lock (this.synLock) if I understand correctly?
I see this a lot:
object lockObj;
List<string> myStrs;
// ...
lock(lockObj)
{
myStrs.Add("hello world");
}
Why have the separate object? Surely you can just do this:
List<string> myStrs;
// ...
lock(myStrs)
{
myStrs.Add("hello world");
}
It is a problem to lock directly on the list only if myStrs is public, and thus can be locked by other callers as well, resulting in a possible deadlock.
If it is a private member, then there should be no problem, but locking on a seperate object is a good habit in any case.
See this similar question for a more detailed answer:
Why is lock(this) {...} bad?
In general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:
lock (this) is a problem if the instance can be accessed publicly.
lock (typeof (MyType)) is a problem if MyType is publicly accessible.
lock(“myLock”) is a problem since any other code in the process using the same string, will share the same lock.
Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
Form the documentation lock c#
The idea is to always lock a private members that can only be accessed by the code that we are looking at. Whereas when we lock the members that we do not have control upon like public member or similar, chances are some other part of code can already hold a lock. This could lead to unexpected blocking behavior.
So, I think this had lead to thumb rule / best practice of having a private object especially for locking.
I would be interested in seeing if there are more reasons coming up.
Your list of string is a list used for internal implementation details.
The problem with the second version could rise if you change your implementation such a way that you re-initilazie the strings list.
Then the thread-safety of your implementation could be broken.
So it's better that you use a seperate object for synchronization and declare this object as read only.
If you use the list as the lock object, and it is reset to null, then the lock(myStringList) will throw an ArgumentNullException. Below the simple test code of a console application.
private static IList<string> mystringList = new List<string>();
static void Main(string[] args)
{
new Thread(() =>
{
try
{
while (true)
{
//Acquire the lock
lock (mystringList)
{
//Do something with the data
Thread.Sleep(100);
Console.WriteLine("Lock acquired");
}
}
}
catch (Exception exception)
{
Console.WriteLine("Exception: " +exception.Message);
}
}).Start();
new Thread(() =>
{
//Suppose we do something
Thread.Sleep(1000);
//And by some how reset the list to null
mystringList = null;
}).Start();
Console.ReadLine();
}
Short version:
For a cache class I need to get notified if an object is garbage collected (to remove the according entries from my cache). What is the best way to do so? Sending an event from the destructor?
Long version:
I am writing a cacher/memoizer for functions that take one huge parameter-tree object and many small value type parameters, e.g.,
double myFunc(HugeParTree parTree, int dynPar1, double dynPar2)
I want to cache these functions in the following way:
Cache results for the tuples (parTree.GUID, dynPar1, dynPar2, ...)
Whenever parTree changes, which seldomly happens, all according cache entries are deleted (via Observer pattern). (parTree.Equals() is just too expensive; it compares 100+ value types).
Code looks like this right now (for one value parameter):
public class CachedFunction1ObsPar1Par<TRet, TObsPar1, TPar1>
where TObsPar1 : IObservable, IProvideGUID
{
public delegate TRet ValueCalculator(TObsPar1 obsPar1, TPar1 par1);
public CachedFunction1ObsPar1Par(ValueCalculator calc)
{
_calc = calc;
}
#region members
private ValueCalculator _calc;
private Dictionary<Guid, Dictionary<TPar1, TRet>> _cache =
new Dictionary<Guid, Dictionary<TPar1,TRet>>();
#endregion
public TRet value(TObsPar1 obsPar1, TPar1 par1)
{
TRet result;
bool cacheHit = checkCache(obsPar1, par1, out result);
if (cacheHit)
{
Debug.Assert(result.Equals(_calc(obsPar1, par1)));
return result;
}
else
{
result = _calc(obsPar1, par1);
_cache[obsPar1.GUID].Add(par1, result);
return result;
}
}
private bool checkCache(TObsPar1 obsPar1, TPar1 par1, out TRet result)
{
if (!_cache.ContainsKey(obsPar1.GUID))
{
_cache.Add(obsPar1.GUID, new Dictionary<TPar1, TRet>());
obsPar1._changed += this.invalidateCache;
}
Dictionary<TPar1, TRet> guidCache = _cache[obsPar1.GUID];
bool success = guidCache.TryGetValue(par1, out result);
return success;
}
private void invalidateCache(object sender)
{
TObsPar1 obsPar = (TObsPar1)sender;
_cache.Remove(obsPar.GUID);
obsPar._changed -= this.invalidateCache;
}
}
I haven't tested this yet, as I still have the problem that cache entries never get removed after the according parTree is not used any more. I'd love a synchronous solution without repeated "scans" for very old cache entries.
For a cache class I need to get notified if an object is garbage
collected (to remove the according entries from my cache). What is the
best way to do so? Sending an event from the destructor?
If your cache holds normal (strong) references the items will never be collected.
If your cache holds WeakReferences you do not have to remove anything.
You could define an interface 'ICacheable' that must be implemented by the objects in the cache. In a method of the interface RemoveFromCache() you could search the cache for its child objects and remove them.
When you remove an item from the cache, test it for the interface and call RemoveFromCache().
This is similar to IDisposable.
Garbage collection is not something to count on because you never know when it will run.
Henk already mentioned the flaw in your requirement.
But, just to answer your question.
To know when an object is being garbage collected you can write a destructor for that object.
~YourClass();
As per MSDN:
This method is automatically called after an object becomes
inaccessible
Though it's never recommended to rely on GC or destructor.
I have this code:
public class EntityMapper<T> where T : IMappingStrategy, new()
{
private static T currentStrategy;
public static T CurrentStrategy
{
get
{
if (currentStrategy == null)
currentStrategy = new T();
return currentStrategy;
}
}
}
Then:
public static void Main()
{
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
EntityMapper<ClientMappingStrategy>.CurrentStrategy.ToString();
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
}
Well, the question is:
Why when i'm debugging i can see that the constructor of ServerBussinessMappingStrategy is called only once time?
This work well, but i undertand why always EntityMapper return the correct instance that i need, only instantiating once time the ServerMappingStrategy class.
Regards!
PD: Sorry my english jeje ;)
The static field is persisted for the duration of your AppDomain, and it is cached when first created:
public static T CurrentStrategy
{
get
{
if (currentStrategy == null) // <====== first use detected
currentStrategy = new T(); // <==== so create new and cache it
return currentStrategy; // <=========== return cached value
}
}
Actually, there is an edge case when it could run twice (or more), but it is unlikely.
This is a pretty common pattern for deferred initialization, and is used pretty much identically in a number of places in the BCL. Note that if it had to happen at most once, it would need either synchronization (lock etc) or something like a nested class with a static initializer.
Normally, it will only get called once. That is, unless you have a race condition.
Let's say two threads execute this statement the same time:
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
Let's say thread A will run up until currentStrategy == null but gets paused before new T() when Windows suddenly gives control to thread B which then makes the comparison again, currentStrategy is still null, invokes the constructor and assigns the new instance to currentStrategy. Then, at some point, Windows gives the control back to thread A that calls the constructor again. This is important because normally static members are (sort of) expected to be thread safe. So if I were you, I would wrap that bit into a lock clause.
P.S. this snippet won't compile as T might be a struct that cannot be a null. Instead of comparing to null, compare to default(T) or specify that T has to be a class.