I'm a little worried about how you use and initialize your critical sections. In my humble opinion, you should do it a little different. Here is a little example.

[pascal]
{

This is an example from the book entitled
"Delphi 6 Developer's Guide".

}

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
ArrSize = 128;

type
{ .: TFooThread :. }
TFooThread = class(TThread)
protected
{ Protected declarations }
procedure Execute(); override;
end;

{ .: TForm1 :. }
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure MyThreadTerminate(Sender: TObject);
public
{ Public declarations }
end;

var
Form1: TForm1;
NextNumber: Integer = 0;
DoneFlags: Integer = 0;
GlobalArray: array[1..ArrSize] of Integer;
CS: TRTLCriticalSection;

implementation

{$R *.dfm}

{ .: GetNextNumber :. }
function GetNextNumber(): Integer;
begin
Result := NextNumber;
Inc(NextNumber);
end;

{ TFooThread }

procedure TFooThread.Execute;
var
I: Integer;
begin
OnTerminate := Form1.MyThreadTerminate;

EnterCriticalSection(CS); // the beginning of a critical section
for I := 1 to ArrSize do
begin
GlobalArray[i] := GetNextNumber();
Sleep(3 + Random(12)); // let other threads work
end;
LeaveCriticalSection(CS); // the end of a critical section
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
InitializeCriticalSection(CS); // initializes critical section
TFooThread.Create(False);
TFooThread.Create(False);
end;

procedure TForm1.MyThreadTerminate(Sender: TObject);
var
I: Integer;
begin
Inc(DoneFlags);
if (DoneFlags = 2) then
begin
for I := 1 to ArrSize do
ListBox1.Items.Add(IntToStr(GlobalArray[I]));
DeleteCriticalSection(CS); // deletes critical section
end;
end;

end.
[/pascal]

Sorry for such a long snippet, but I thought it could be useful for you. What is the most important in this code? This little fragment:

[pascal]
for I := 1 to ArrSize do
begin
GlobalArray[I] := GetNextNumber();
Sleep(3 + Random(12)); // let other threads work
end;
[/pascal]

Don't forget to use Sleep command, because you allow other threads work then. It's very important!

Hope that helps.