title: "Out of memory" error when using TTask.Run for a large number of job running in parallel
body: <p>I am trying to use the new <code>Parallel Programming Library</code> or <code>System.Threading.pas</code> in <code>Delphi</code>.</p>
  
  <p>I have a large number of jobs to work in parallel using <code>TTask.Run</code>.  Here is the code snippet:</p>
  
  <pre><code>var D: TDataSet;
      T: ITask;
      TaskList: TList&lt;ITask&gt;;
      Q: TThreadedQueue&lt;TData&gt;;
  begin
    Q := TThreadedQueue&lt;TData&gt;.Create;
  
    D := Create_Uni_Direction_DataSet;
    D.Open;
  
    TaskList := TList&lt;ITask&gt;.Create;
  
    while not D.Eof do begin
      Q.PushItem(GetData(D));
      T := TTask.Run(
             procedure begin
             var A: TData;
             begin
               A := Q.PopItem;
               Process(A);
               ...
             end
           );
      D.Next;
      TaskList.Add(T);
    end;
  
    TTask.WaitForAll(TaskList.ToArray);
    ...
  
    TaskList.Free;
    Q.Free;
  end;
  </code></pre>
  
  <p>Please note that the code has simplified for illustration purpose.</p>
  
  <p>The code will return <code>Out of Memory</code> error at runtime in Win32 platform.</p>
  
  <p>The memory issue is obvious due to I attempt to keep a large number of ITask reference in <code>TaskList</code>.</p>
  
  <p>There are some reasons why I use <code>TTask.Run</code> instead of <code>TParallel</code>:</p>
  
  <ol>
  <li>I couldn't determine the Low and High bound of tasks. e.g.: uni-directional dataset</li>
  <li>The threaded task update UI control to report status via <code>TThread.Synchronize</code>.  Using <code>TThread.Synchronize</code> in <code>TParallel</code> will freeze application.</li>
  </ol>
  
  <p>As I want to monitor and make sure these tasks shall execute before it continue on, I use <code>TTask.WaitForAll</code> to check items in <code>TaskList.ToArray</code>.</p>
  
  <p>Apparently, there should have a number of tasks complete execution while the <code>for</code> loop still working.  These completed tasks are no longer needed for to be monitored and thus may remove from <code>TaskList</code>.</p>
  
  <p>However, it is not easy to decide or get notified if tasks has complete it's job.  Perhaps there are methods or ready constructs in Delphi's <code>PPL</code> that can solve my problem that I am not aware of.  Please share your ideas or solutions.</p>