title: Asp.net MVC API lock a function based on method parameters
body: <p>I have a helper function which deserializes an XML file, and generates c# objects from it.</p>
  
  <p>After that, the objects are added into server memory. The only way of adding something in the server's memory is only through this function.</p>
  
  <pre><code>public class DeserializeXmlHelper
  {
      public void DeserializeXml(Guid xml_Id, decimal version)
      {
          // heavy process here which takes about 3 seconds
      }
  }
  </code></pre>
  
  <p>This function is being called by different clients using an API method (made in Asp.net MVC API).</p>
  
  <p>When calling the API, can i prevent the execution of the function if somebody else already called the same function with the same parameters?</p>
  
  <p>Something like this, but i don't know if it is a good way of doing it.</p>
  
  <pre><code>public class DeserializeXmlHelper
  {
      private static readonly ConcurrentDictionary&lt;string, object&gt; _processes = new ConcurrentDictionary&lt;string, object&gt;();
  
      public void DeserializeXml(Guid xml_Id, decimal version)
      {
          string processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
          object processLocker = null;
          if (_processes.TryGetValue(processKey, out processLocker) == false)
          {
              processLocker = new object();
              _processes.TryAdd(processKey, processLocker);
          }
  
          lock (processLocker)
          {
              // heavy process here which takes about 3 seconds
  
              _processes.TryRemove(processKey);
          }
      }
  }
  </code></pre>
  
  <p><strong>EDITED - New version</strong></p>
  
  <p>Tim Roger's answer is working successfully.</p>
  
  <p>However, if i want to return only when the initial call has finished, can i do something like this? (I am using ConcurrentDictionary because i don't know how to add locks, but the idea should be the same)</p>
  
  <pre><code>public class DeserializeXmlHelper
  {
      private static readonly ConcurrentDictionary&lt;string, string&gt; _processes = new ConcurrentDictionary&lt;string, string&gt;();
      public void DeserializeXml(Guid xml_Id, decimal version)
      {
          string _processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
          string _processValue = null;
          if (_processes.TryGetValue(_processKey, out _processValue) == true)
          {
              // function already called with the same parameters
              do
              {
                  System.Threading.Thread.Sleep(100);
              }
              while(_processes.TryGetValue(_processKey, out _processValue) == true)
  
              return;
          }
  
          try
          {
              _processes.TryAdd(_processKey, _processValue);
  
              var begin = "begin process";
  
              System.Threading.Thread.Sleep(10000);
  
              var end = "ending process";
          }
          finally
          {
              _processes.TryRemove(_processKey, out _processValue);
          }
      }
  }
  </code></pre>