2
\$\begingroup\$

I have a case where I match data from DB by the various filters. Until the match is updated in the DB, I don't want to accept requests for matching with the same criteria, as this could produce duplicate matches. Therefore I "lock", but selectively using AsyncLock from AsyncEx library. I've checked the correctness of the implementation with logging and it seems do do things right, but Is my implementation correct and without dead-lock risk? This is in the web app, so the AsyncLock in static ConcurrentDictionary will be long-lived. Should it matter?

public class Handler
{
    /// <summary>
    /// Container of objects that we lock over for matching the data.
    /// </summary>
    private static readonly ConcurrentDictionary<string, AsyncLock> LockMap = new ConcurrentDictionary<string, AsyncLock>();            

    public async Task<MyResult> Handle(Command command, CancellationToken cancellationToken)
    {
        string lockKey = $"{command.SomeValue1}_{command.SomeValue2}";

        using (await LockMap.GetOrAdd(lockKey, _ => new AsyncLock()).LockAsync())
        {
            var allocations = await repository.GetDataAsync(command.SomeValue1, command.SomeValue2);
            var result = Process(allocations);
            return await repository.UpdateAsync(result);
        }
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Maybe you could use ConditionalWeakTable \$\endgroup\$ – firda Nov 20 '18 at 20:59
  • \$\begingroup\$ Thanks @firda, didn't know about ConditionalWeakTable. Will try it out.Do you think there is something to be feared of, if I make the AsyncLock long-lived? \$\endgroup\$ – the berserker Nov 21 '18 at 8:34
  • \$\begingroup\$ It is more about the number of possible commands. It would be better if you make your question a bit more concrete, add more context. I am assuming that the dictionary can grow over time to unbearable size, therefore suggested that conditional weak table (or any other mechanism that would remove the keys / dictionary entries including the async lock). It also looks like you just want to delay matching requests, not to run them at the same time, but not refusing them. Probably intentional. \$\endgroup\$ – firda Nov 21 '18 at 8:42
  • \$\begingroup\$ OK, I see. Yes the intention is as you have mentioned it. There are about 10 available possibilities for keys for AsyncLock instances, so this should be good then, even without ConditionalWeakTable. Thank a lot for your input. \$\endgroup\$ – the berserker Nov 21 '18 at 12:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.