title: Correct way to convert method to async in C#?
body: <p>I'm attempting to convert the following method (simplified example) to be asynchronous, as the <code>cacheMissResolver</code> call may be expensive in terms of time (database lookup, network call):</p>
  
  <pre><code>// Synchronous version
  public class ThingCache
  {
      private static readonly object _lockObj;
      // ... other stuff
  
      public Thing Get(string key, Func&lt;Thing&gt; cacheMissResolver)
      {
          if (cache.Contains(key))
              return cache[key];
  
          Thing item;
  
          lock(_lockObj)
          {
              if (cache.Contains(key))
                  return cache[key];
  
              item = cacheMissResolver();    
              cache.Add(key, item);
          }
  
          return item;
      }
  }
  </code></pre>
  
  <p>There are plenty of materials on-line about consuming async methods, but the advice I have found on producing them seems less clear-cut. Given that this is intended to be part of a library, are either of my attempts below correct?</p>
  
  <pre><code>// Asynchronous attempts
  public class ThingCache
  {
      private static readonly SemaphoreSlim _lockObj = new SemaphoreSlim(1);
      // ... other stuff
  
      // attempt #1
      public async Task&lt;Thing&gt; Get(string key, Func&lt;Thing&gt; cacheMissResolver)
      {
          if (cache.Contains(key))
              return await Task.FromResult(cache[key]);
  
          Thing item;
  
          await _lockObj.WaitAsync();
  
          try
          {
              if (cache.Contains(key))
                  return await Task.FromResult(cache[key]);
  
              item = await Task.Run(cacheMissResolver).ConfigureAwait(false);
              _cache.Add(key, item);
          }
          finally
          {
              _lockObj.Release();
          }
  
          return item;
      }
  
      // attempt #2
      public async Task&lt;Thing&gt; Get(string key, Func&lt;Task&lt;Thing&gt;&gt; cacheMissResolver)
      {
          if (cache.Contains(key))
              return await Task.FromResult(cache[key]);
  
          Thing item;
  
          await _lockObj.WaitAsync();
  
          try
          {
              if (cache.Contains(key))
                  return await Task.FromResult(cache[key]);
  
              item = await cacheMissResolver().ConfigureAwait(false);
              _cache.Add(key, item);
          }
          finally
          {
              _lockObj.Release();
          }
  
          return item;
      }
  }
  </code></pre>
  
  <p>Is using <code>SemaphoreSlim</code> the correct way to replace a lock statement in an async method? (I can't await in the body of a lock statement.)</p>
  
  <p>Should I make the <code>cacheMissResolver</code> argument of type <code>Func&lt;Task&lt;Thing&gt;&gt;</code> instead? Although this puts the burden of making sure the resolver func is async on the caller (wrapping in <code>Task.Run</code>, I know it will be offloaded to a background thread if it takes a long time).</p>
  
  <p>Thanks.</p>