0

The given code attempts to run a fire-and-forget Task while acquiring a lock to avoid race conditions on a cached element. while debugging the whole application I noticed bizarre behavior - getting to the same break point with the same key. That said, I'm not sure if the assumption that ConcurrentDictionary guarantees that only one writer will be applied to the element as well as locking inside the Task.Run block will assure me that this and only this Task will have access to the element itself.

    Task.Run(() =>
    {
        lock (GetLockContext(key, region))
        {
            try
            {
                object newValue = cacheInterceptor.Intercept<T>(ctx);
                Put(refreshContext.Key, newValue, refreshContext.Region, refreshAction);
            }
            catch (Exception ex)
            {
                refreshContext.UpdteRefreshNeeded(true);
                LogError("HANDLE_REFRESH", null, null, ex);
            }
        });
    }
        private object GetLockContext(string key, string region)
        {
            string ctx = key + region;
            object lckCtx = CTX_REPO.GetOrAdd(ctx, (dontcare) => new object());

            return lckCtx;
        }
private static readonly ConcurrentDictionary<string, object> CTX_REPO
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
OmerMichleviz
  • 93
  • 1
  • 6

1 Answers1

0

The lock (GetLockContext(key, region)) should guarantee that only one thread in the current process will enter the critical region for the same key/region combination. The only problems that I can think of are:

  1. The key + region generates the same combination for different key/region pairs. For example "ab" + "c" and "a" + "bc".
  2. Your application is hosted, and the host starts a new process before the currently running process has terminated.

As a side note instead of locking synchronously you could consider using an asynchronous locker like the SemaphoreSlim class, in order to avoid blocking ThreadPool threads. You could check out this question for ideas: Asynchronous locking based on a key.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104