Когда вы создаете класс потока, добавьте переменную для хранения идентификатора панели:
type
TMyThread = class(TThread)
public
PanelId: integer;
constructor Create(APanelId: integer);
end;
constructor TMyThread.Create(APanelId: integer);
begin
inherited Create({CreateSuspended=}true);
PanelId := APanelId;
Suspended := false;
end;
Для каждого потока создайте панель и установите для ее значения тега следующий идентификатор:
for i := 1 to MaxThreads do begin
threads[i] := TMyThread.Create(i);
panels[i] := TPanel.Create(Self);
panels[i].Tag := i;
end;
Когда вашей теме необходимо обновить данные на панели, она должна отправить специально определенное сообщение в основную форму:
const
WM_CONNECTED = WM_USER + 1;
WM_DISCONNECTED = WM_USER + 2;
В wParam этого сообщения вы передаете PanelId:
procedure TMyThread.Connected;
begin
PostMessage(MainForm.Handle, WM_CONNECTED, PanelId, 0);
end;
В MainForm вы ловите это сообщение, находите панель и обновляете ее:
TMainForm = class(TForm)
{....}
protected
procedure WmConnected(var msg: TMessage); message WM_CONNECTED;
end;
{...}
procedure TMainForm.WmConnected(var msg: TMessage);
begin
panels[msg.wParam].Color := clGreen;
end;
То же самое с WmDisconnected.
Здесь важно то, что вы НЕ МОЖЕТЕ и НИКОГДА не должны пытаться обновлять визуальные компоненты из потоков, отличных от основного потока. Если вам нужно обновить пользовательские элементы управления, вы должны публиковать сообщения в главной форме и создавать процедуры-обработчики, как в этом примере. Эти процедуры обработчика будут автоматически вызываться из основного потока.