Problem
This code uses a ReaderWriterLockSlim
to store data (on a disk or wherever), so that only one thread can write and many threads can read.
All writers should be finished before reading, and the write should not block the caller.
Basically my solution would work, but it doesn’t look and feel natural to .NET since 4.0 the Task Parallel Library (TPL) was introduced…
class JsonApplicationContainerDAO : IApplicationContainerDAO
{
private static volatile IApplicationContainerDAO instance;
private static object syncRoot = new Object();
private readonly BlockingCollection<ICollection<IApplicationConfiguration>> itemsToSave = new BlockingCollection<ICollection<IApplicationConfiguration>>();
private readonly Thread writerThread ;
private readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();
public static IApplicationContainerDAO Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new JsonApplicationContainerDAO();
}
}
return instance;
}
}
private JsonApplicationContainerDAO()
{
writerThread = new Thread(WriteItems);
writerThread.Start();
}
private void WriteItems(object obj)
{
ICollection<IApplicationConfiguration> item = null;
while((item = itemsToSave.Take()) != null){
try
{
readerWriterLock.EnterWriteLock();
//do stream stuff here
}
finally
{
readerWriterLock.ExitWriteLock();
}
}
}
public ICollection<IApplicationConfiguration> LoadAll()
{
try
{
readerWriterLock.EnterReadLock();
//do stream stuff here
}
finally
{
readerWriterLock.ExitReadLock();
}
return null;
}
public void Persist(ICollection<IApplicationConfiguration> items)
{
itemsToSave.Add(items);
}
}
Solution
-
For this:
try { readerWriterLock.EnterWriteLock(); //do stream stuff here } finally { readerWriterLock.ExitWriteLock(); }
EnterWriteLock
should be before thetry
statement.Suppose the
EnterWriteLock()
fails. For whatever reason.
Then the one thing you shouldn’t do is to Exit a lock you never Entered. -
Please note that singleton nowadays is rather an antipattern. They make testing harder and often hide dependencies which leads to spaghetti code which is really hard to work with. What is so bad about singletons?