Assigning a Panel to each thread- Delphi

2020-07-27 02:19发布

问题:

I have a program running several threads simultaneously. Each thread connects a database and transfers data from one table to another. Now I want to assign a panel to each thread in the MainForm so I can change color of the Panel to green if the connection is successful or to red if it's broken after a number of retries.

So how can I tell a thread which Panel is its own Panel?

回答1:

When you create a thread class, add a variable to store panel id:

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 every thread create a panel and set it's Tag value to this Id:

for i := 1 to MaxThreads do begin
  threads[i] := TMyThread.Create(i);
  panels[i] := TPanel.Create(Self);
  panels[i].Tag := i;
end;

When your thread needs to update data on panel, it should send a specially defined message to the main form:

const
  WM_CONNECTED = WM_USER + 1;
  WM_DISCONNECTED = WM_USER + 2;

In wParam of this message you pass PanelId:

procedure TMyThread.Connected;
begin
  PostMessage(MainForm.Handle, WM_CONNECTED, PanelId, 0);
end;

In MainForm you catch this message, find the panel and update it:

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;

Same with WmDisconnected.

The important thing here is that you CANNOT and NEVER should try to update visual components from threads other than the main thread. If you need to update user controls, you should post messages to the main form and create handler procedures, like in this example. These handler procedures will then be automatically called from the main thread.



回答2:

you really shouldn't be doing this - the UI should only be updated by the main thread.



回答3:

You can not assign panel of main form thread because it is not thread-safe to update it. The thread can comunicate with application thread (main form) via windows messages or you must to use message queue. Check OmniThreadLibrary to simplify your work.