title: Using SemaphoreSlim and Dictionary to wait for a NetMQ reply
body: <p>I have two applications communicating with each other using NetMQ. The first application has an API controller built into it, and the second application(the engine) communicates back and forth with the first application when necessary. All of the API controller functions are Async Task because we expect many requests at the same time to be happening. </p>
  
  <p>One of these API controller functions needs to first send a NetMQ message to the second application(the engine) and wait for its response before returning the result to the API function requester (the API user). It needs to do all this in an asynchronous manner without grabbing from the thread pool, because as I said earlier we may have a large amount of requests constantly hitting this controller. </p>
  
  <p>While the SemaphoreSlim is waiting, the second application(the engine) is updating the status of a specific record in the database, and its the status of this record that I need to read in the API controller function and return to the API user, if I have no SemaphoreSlim wait design, then of course the code will read the database record to early and not return the correct status. So the solution is to create the wait, allow the engine to update the status, and then inform the API controller function that it can read the newly updated status from the database.</p>
  
  <p>I was informed by a colleague to use a SemaphoreSlim and Dictionary setup to create a wait in the function by locking, and only releasing the SemaphoreSlim from the dictionary when it receives the NetMQ reply from the engine. Then naturally the code would continue on where I would check the database for the updated status and return it to the API user.</p>
  
  <p>The problem is that the API controller function completely ignores the SemaphoreSlim lock and reads from the database too early. Most likely because its asynchronous, so my question is, how can I make the SempahoreSlim lock and read from database code work together in an asynchronous fashion without locking the thread?</p>
  
  <p>I'm sure the code will give you a better understanding of what I'm trying to do.</p>
  
  <p><strong>1. Part of API Controller Function code:</strong></p>
  
  <pre><code>//Call Engine
  Messenging.Queue.Enqueue(OrderPositionText + " " + UserId + " " + AssetPairId + " " + OrderType + " " + OrderRequestId + " " + rAmount + " " + rPrice + " " + Stop);
  
  //Create SemaphoreSlim Lock and add it to global Dictionary     
  var NewSemaphore = new SemaphoreSlim(1, 1);
  await NewSemaphore.WaitAsync().ConfigureAwait(false);
  ApiHub.UserSemaphoreDictionary.TryAdd(UserId, NewSemaphore);
  
  //Lock was released lets now read record in Database then return appropriate result to API user.
                  Debug.WriteLine("Checking order status for " + uuid);
                  OrderRequest OrderRequestRec = await _context.OrderRequest.Where(x =&gt; x.UUID == uuid).FirstOrDefaultAsync();
  
      if (OrderRequestRec != null)
                      {
                          Debug.WriteLine("ORDER STATUS: " + OrderRequestRec.Status);
      }
  </code></pre>
  
  <p><strong>2. This is the code in another class that receives the NetMQ message and releases the SemaphoreSlim:</strong></p>
  
  <pre><code>                        //API Semaphore Release lock
                          SemaphoreSlim checkUserId;
                          if (ApiHub.UserSemaphoreDictionary.TryGetValue(UserId, out checkUserId)) {
                              Debug.WriteLine("RELEASING LOCK: " + UserId);
                              checkUserId.Release();
                          }
  </code></pre>
  
  <p>The results are that the Database is read first, then the SemaphoreSlim is released. I need the SemaphoreSlim to be released, then the database read.</p>
  
  <p><strong>EDIT:</strong> I followed the suggestion below and came up with this working code, but my question is now this, is this asynchronous? Will it block the thread while its doing await tc.Task ?</p>
  
  <p><strong>Class:</strong></p>
  
  <pre><code>  TaskCompletionSource&lt;bool&gt; checkUserId;
                                      if (ApiHub.UserSemaphoreDictionary.TryGetValue(UserId, out checkUserId))
                                      {
                                      Debug.WriteLine("RELEASING LOCK: " + UserId);
                                      checkUserId.SetResult(true);
                                      ApiHub.UserSemaphoreDictionary.Remove(UserId);
                                      }
  </code></pre>
  
  <p><strong>Controller:</strong></p>
  
  <pre><code>TaskCompletionSource&lt;bool&gt; tc = new TaskCompletionSource&lt;bool&gt;();
  ApiHub.UserSemaphoreDictionary.TryAdd(UserId, tc);
  
      Debug.WriteLine("BEFORE TC");
      await tc.Task;
      Debug.WriteLine("AFTER TC");
  </code></pre>