6
\$\begingroup\$

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);
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ and the question is? BTW: you start the writer thread in constructor but when does that thread end and when does Take return null? You seem to always "append" to the persistence layer (file) - do you ever need to remove items? Can multiple threads concurrently call Persist/why use BlockingCollection? \$\endgroup\$
    – bkdc
    Commented Mar 12, 2014 at 11:18
  • \$\begingroup\$ The question is, is there a better way with usage of the Task Parrallel Library Blocking queue is used i want to have the write in some kind transactional, so like a Queue i will write every object in the order it has been added to the collection... i abstracted the logic of the write here because it has nothing to do with the problem/question.. The in this sample the thread will never return \$\endgroup\$ Commented Mar 13, 2014 at 12:26

1 Answer 1

4
\$\begingroup\$
  1. For this:

    try
    {
        readerWriterLock.EnterWriteLock();
        //do stream stuff here
    }
    finally
    {
        readerWriterLock.ExitWriteLock(); 
    }
    

    EnterWriteLock should be before the try statement.

    Suppose the EnterWriteLock() fails. For whatever reason. Then the one thing you shouldn't do is to Exit a lock you never Entered.

    Source: C# - Lock question using EnterWriteLock

  2. 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?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.