Назначение панели для каждого потока - Delphi - PullRequest
2 голосов
/ 07 декабря 2010

У меня есть программа, запускающая несколько потоков одновременно. Каждый поток соединяет базу данных и передает данные из одной таблицы в другую. Теперь я хочу назначить панель каждому потоку в MainForm, чтобы я мог изменить цвет панели на зеленый, если соединение установлено успешно, или на красный, если оно разорвано после нескольких попыток.

Так как я могу сообщить ветке, какая панель является собственной панелью?

Ответы [ 3 ]

10 голосов
/ 07 декабря 2010

Когда вы создаете класс потока, добавьте переменную для хранения идентификатора панели:

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.

Здесь важно то, что вы НЕ МОЖЕТЕ и НИКОГДА не должны пытаться обновлять визуальные компоненты из потоков, отличных от основного потока. Если вам нужно обновить пользовательские элементы управления, вы должны публиковать сообщения в главной форме и создавать процедуры-обработчики, как в этом примере. Эти процедуры обработчика будут автоматически вызываться из основного потока.

3 голосов
/ 07 декабря 2010

вы действительно не должны этого делать - пользовательский интерфейс должен обновляться только основным потоком.

1 голос
/ 07 декабря 2010

Вы не можете назначить панель основного потока формы, потому что это не безопасно для потока, чтобы обновить это. Поток может взаимодействовать с потоком приложения (основной формой) через сообщения Windows, или вы должны использовать очередь сообщений. Отметьте OmniThreadLibrary , чтобы упростить вашу работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...