title: Do Tasks generated by TaskCompletionSource need to be Dispose()d?
body: <p>I'm using <code>TaskCompletionSource</code> in my software to distribute network packets to <code>async</code>/<code>await</code> methods. So in my code, there are various points where the software needs to wait for a network packet getting demultiplexed from the receive handler and handed over to a method <code>async Wait()</code>. There can be many, many packets per second and I'm deciding if I want to push the packet to <code>TaskCompletionSource</code> or put it into a <code>Queue</code>. So, whenever theres no <code>TaskCompletionSource</code> I will create a new one, which leads to a new <code>Task</code> object.</p>
  
  <p>According to this question <a href="https://stackoverflow.com/questions/5985973">Do I need to dispose of a Task?</a> and according to this blog <a href="https://blogs.msdn.microsoft.com/pfxteam/2012/03/25/do-i-need-to-dispose-of-tasks/" rel="noreferrer">Parallel Programming with .NET</a> <code>Task</code>s don't need be <code>Dispose</code>d. However, I'm sometimes instantiating many thousand <code>TaskCompletionSource</code> per second. The detailed answer in the linked blog also says, that <code>Task</code> may use internally <code>WaitHandle</code>. Now I have the strong feeling that my case is the exact case, where I should use <code>Dispose</code> on the tasks from the <code>TaskCompletionSource</code>.</p>
  
  <p>This is how I wait for a new packet. This method will be calles with <code>await</code> and can also be called heavily in parallel:</p>
  
  <pre><code>public async Task&lt;Packet&gt; Wait()
  {
      Packet packet;
  
      lock (sync)
          if (packets.TryDequeue(out packet))
              return packet;
          else
              waiter = new TaskCompletionSource&lt;Packet&gt;();
  
      return await waiter.Task;
  }
  </code></pre>
  
  <p>My method of pushing packets from the network handler looks like this:</p>
  
  <pre><code>public void Poke(Packet packet)
  {
      lock (sync)
          if (waiter == null)
              packets.Enqueue(packet);
          else
              waiter.SetResult(packet);
  }
  </code></pre>
  
  <p>I'm on .NET Core >= 2.2. The blog entry states that the behavior of <code>WaitHandle</code> also changed in .NET 4.5.</p>
  
  <p><strong>Question: Do I need to Dispose <code>Task</code>s in this specific scenario? Will I create many <code>Handles</code>, if I don't <code>Dispose</code> the Tasks created by <code>TaskCompletionSource</code> when receiving many packets coming along this code path? Is this the scenario the blog entry warned me about?</strong></p>
  
  <p><em>Please refrain from telling me, that this method is a bad choice as long as you can't tell me a better method being very compatible to <code>async</code>/<code>await</code> pattern and also being able to distribute those packets to various selected listeners. Please also don't tell me, that creating many objects because of many network packets is generally a bad idea.</em></p>