title: When to cache Tasks?
body: <p>I was watching <a href="https://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-829T" rel="nofollow noreferrer">The zen of async: Best practices for best performance</a> and <a href="https://social.msdn.microsoft.com/profile/stephen%20toub%20-%20msft/" rel="nofollow noreferrer">Stephen Toub</a> started to talk about Task caching, where instead of caching the results of task jobs you cache the tasks themselves. As far as i understood starting a new task for every job is expensive and it should be minimized as much as possible. At around 28:00 he showed this method:</p>
  
  <pre><code>private static ConcurrentDictionary&lt;string, string&gt; s_urlToContents;
  
  public static async Task&lt;string&gt; GetContentsAsync(string url)
  {
      string contents;
      if(!s_urlToContents.TryGetValue(url, out contents))
      {
          var response = await new HttpClient().GetAsync(url);
          contents = response.EnsureSuccessStatusCode().Content.ReadAsString();
          s_urlToContents.TryAdd(url, contents);
      }
      return contents;
  }
  </code></pre>
  
  <p>Which at a first look looks like a good thought out method where you cache results, i didn't event think about caching the job of getting the contents.</p>
  
  <p>And than he showed this method:</p>
  
  <pre><code>private static ConcurrentDictionary&lt;string, Task&lt;string&gt;&gt; s_urlToContents;
  
  public static Task&lt;string&gt; GetContentsAsync(string url)
  {
      Task&lt;string&gt; contents;
      if(!s_urlToContents.TryGetValue(url, out contents))
      {
          contents = GetContentsAsync(url);
          contents.ContinueWith(t =&gt; s_urlToContents.TryAdd(url, t); },
          TaskContinuationOptions.OnlyOnRanToCompletion |
          TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
      }
      return contents;
  }
  
  private static async Task&lt;string&gt; GetContentsAsync(string url)
  {
      var response = await new HttpClient().GetAsync(url);
      return response.EnsureSuccessStatusCode().Content.ReadAsString();
  }
  </code></pre>
  
  <p>I have trouble understanding how this actually helps more than just storing the results.</p>
  
  <p>Does this mean that you're using less Tasks to get the data?</p>
  
  <p>And also, how do we know when to cache tasks? As far as i understand if you're caching in the wrong place you just get a load of overhead and stress the system too much</p>