Simply being lazy and concurrent

by dotnetnerd 18. November 2017 20:25

I recently worked on a long running migration project, where we needed to ensure that some of the sql migration scripts were only called once per entity that was migrated, in a threadsafe manner. I looked to the System.Collections.Concurrent namespace, but none of the classes were really a good match. Basically what I needed was the ability to run a part of the migration that was identified by key, but ensure that it would only run once, although different parent strategies might try and run it.

The closest thing I could find was the ConcurrentDictionary. It does however not gurantee that the function passed to GetOrAdd is not called multiple times, and of course I did not really need for it to be a dictionary. I came up with this little implementation, that uses the ConcurrentDictionary internally and combines it with Lazy<T> to ensure that the code only runs once.

using System;
using System.Collections.Concurrent;
using System.Threading;

namespace MyAwesomeSauce
{
    public class OnetimeCollection<TKey>
    {
        private readonly ConcurrentDictionary<TKey, Lazy<string>> concurrentDictionary
            = new ConcurrentDictionary<TKey, Lazy<string>>();

        public void Run(TKey key, Action<TKey> valueFactory)
        {
            var lazyResult = concurrentDictionary.GetOrAdd(key, k =>
                 new Lazy<string>(() => {
                    valueFactory(k);
                    return string.Empty;
                 }, LazyThreadSafetyMode.ExecutionAndPublication));

            var holeInTheGround = lazyResult.Value;
        }
    }
}

With this in place all I needed was a singleton instance, and to wrap each job in a call to Run. Nice and pragmatic solution.

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List