KeyLocks: Lock .NET/C#-code on Specific Values

If you've ever needed to ensure that multiple threads are not running the same code, you've probably used a lock-statement in your .NET/C#-code.

Sometimes a regular lock can be too aggressive and lock too much running code for too long. You can solve this by cleverly locking on unique objects, but that handling is complex, error-prone and can become tedious.

Many times you know that you have a specific value or ID which is the key you want to lock on. For instance, you might want your code to not write to the database from multiple actions performed in parallel on your web-application. Using the Nuget-package KeyLocks will give you easy to write syntax to handle this:

private static KeyLock<string> _keyLock = new KeyLock<string>();

public void Main()
        () => { UpdateData("entity-123", "First new value"); },
        () => { UpdateData("entity-123", "Second new value"); }, // This will await line above
        () => { UpdateData("another-entity-456", "Another new value"); },        
        () => { UpdateData("yet-another-entity-789", "Yet another new value"); });

private void UpdateData(string id, string value)
    _keyLock.RunWithLock(id, () =>
        // Execute locked code

Make sure the instance of KeyLock<T> is shared between threads executing the code you want to lock on. In this case, I solved it by making the instance static and therefore shared across all instances of the code using it.

The package also contains the type NameLock is a short-hand term for KeyLock<string>. It defaults to being case-sensitive, but that can be changed by passing the correct IEqualityComparer<T> as a constructor-argument like this:

var nameLock = new NameLock(StringComparer.InvariantCultureIgnoreCase)

See the README-file on GitHub for the latest detailed information about KeyLocks. Or try it out through Nuget by running Install-Package KeyLocks in your project. You can even follow the absolutely latest build on MyGet.