Why i get an exception argument out of range?
<p>Can someone can explain me why i receive sometime an Exception "Argument out of range" under the ios simulator when i execute the code below? on android i never get any error. I use Delphi berlin.</p>

<p>the functions where the error appear :</p>

<pre><code>{**********************************************************************}
procedure Twin_WorkerThreadPool.Enqueue(const Value: Twin_WorkerThread);
begin
  Tmonitor.Enter(fPool);
  try
    fPool.Add(Value);
    fSignal.SetEvent;
  finally
    Tmonitor.Exit(fPool);
  end;
end;

{********************************************************}
function Twin_WorkerThreadPool.Dequeue: Twin_WorkerThread;
begin
  Tmonitor.Enter(self); // &lt;&lt; only one thread can execute the code below
  try

    Tmonitor.Enter(fPool);
    try
      if Fpool.Count &gt; 0 then begin
        result := fPool[Fpool.Count - 1];
        fPool.Delete(Fpool.Count - 1);
        exit;
      end;
      fSignal.ResetEvent;
    finally
      Tmonitor.Exit(fPool);
    end;

    fSignal.WaitFor(Infinite);

    Tmonitor.Enter(fPool);
    try
      result := fPool[Fpool.Count - 1]; // &lt;&lt; exception argument out of range ? but how it's possible ?
      fPool.Delete(Fpool.Count - 1);
    finally
      Tmonitor.Exit(fPool);
    end;

  finally
    Tmonitor.exit(self);
  end;
end;
</code></pre>

<p>Below the full source code :</p>

<pre><code>  {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
  Twin_WorkerThreadPool = class(TObject)
  private
    fPool: TObjectList&lt;Twin_WorkerThread&gt;;
    fSignal: Tevent;
  public
    procedure Enqueue(const Value: Twin_WorkerThread);
    function Dequeue: Twin_WorkerThread;
  end;

{***********************************}
constructor Twin_WorkerThread.Create;
begin
  FProc := nil;
  FProcReadySignal := TEvent.Create(nil, false{ManualReset}, false, '');
  FProcFinishedSignal := TEvent.Create(nil, false{ManualReset}, false, '');
  inherited Create(False); // see http://www.gerixsoft.com/blog/delphi/fixing-symbol-resume-deprecated-warning-delphi-2010
end;

{***********************************}
destructor Twin_WorkerThread.Destroy;
begin
  Terminate;
  FProcReadySignal.setevent;
  WaitFor;
  FProcReadySignal.Free;
  FProcFinishedSignal.Free;
  inherited;
end;

{**********************************}
procedure Twin_WorkerThread.Execute;
begin
  while True do begin
    try

      //wait the signal
      FProcReadySignal.WaitFor(INFINITE);

      //if terminated then exit
      if Terminated then Break;

      //execute fProc
      if assigned(FProc) then FProc();

      //signal the proc is finished
      FProcFinishedSignal.SetEvent;

    except
      //hide the exception
    end;
  end;
end;

{**********************************************************}
procedure Twin_WorkerThread.ExecuteProc(const AProc: TProc);
begin
  fProc := AProc;
  FProcFinishedSignal.ResetEvent;
  FProcReadySignal.SetEvent;
end;

{*****************************************************************}
procedure Twin_WorkerThread.ExecuteAndWaitProc(const AProc: TProc);
begin
  fProc := AProc;
  FProcFinishedSignal.ResetEvent;
  FProcReadySignal.SetEvent;
  FProcFinishedSignal.WaitFor(INFINITE);
end;

{********************************************************************}
constructor Twin_WorkerThreadPool.Create(const aThreadCount: integer);
var i: integer;
begin
  fPool := TObjectList&lt;Twin_WorkerThread&gt;.create(false{aOwnObjects});
  fSignal := TEvent.Create(nil, false{ManualReset}, false, '');
  for I := 0 to aThreadCount - 1 do
    fPool.Add(Twin_WorkerThread.Create)
end;

{***************************************}
destructor Twin_WorkerThreadPool.Destroy;
var i: integer;
begin
  for I := 0 to fPool.Count - 1 do begin
    fPool[i].disposeOf;
    fPool[i] := nil;
  end;
  fPool.Free;
  fSignal.Free;
  inherited Destroy;
end;

{*********************************************************************}
procedure Twin_WorkerThreadPool.ExecuteAndWaitProc(const AProc: TProc);
var aThread: Twin_WorkerThread;
begin
  aThread := Dequeue;
  try
    aThread.ExecuteAndWaitProc(aProc);
  finally
    Enqueue(aThread);
  end;
end;
</code></pre>

<p>NOTE:</p>

<p>Just to explain a little better, remember it's only on ios it's not work, and if i add a sleep(1000) after the fSignal.resetEvent then it's work :</p>

<pre><code>    Tmonitor.Enter(fPool);
    try
      if Fpool.Count &gt; 0 then begin
        result := fPool[Fpool.Count - 1];
        fPool.Delete(Fpool.Count - 1);
        exit;
      end;
      fSignal.ResetEvent;

      sleep(1000);   

    finally
      Tmonitor.Exit(fPool);
    end;

    fSignal.WaitFor(Infinite);
</code></pre>

<p>so it's look like that the signal is not set to OFF just after doing fSignal.ResetEvent; </p>

<p>i m affraid it's a bug in TEvent or Tmonitor :(</p>