为每个线程分配一个面板 - Delphi

发布于 2024-10-06 14:27:59 字数 168 浏览 2 评论 0原文

我有一个程序同时运行多个线程。每个线程连接一个数据库并将数据从一个表传输到另一个表。现在我想为 MainForm 中的每个线程分配一个面板,这样如果连接成功,我可以将面板的颜色更改为绿色;如果在多次重试后连接中断,则可以将面板的颜色更改为红色。

那么我怎样才能告诉线程哪个Panel是它自己的Panel呢?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

念三年u 2024-10-13 14:27:59

当你创建一个线程类时,添加一个变量来存储面板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;

为每个线程创建一个面板并将其Tag值设置为此Id:

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

当你的线程需要更新面板上的数据时,它应该向主线程发送一个特殊定义的消息form:

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 相同。

这里重要的是,您不能也不应该尝试从主线程以外的线程更新可视组件。如果需要更新用户控件,则应将消息发布到主窗体并创建处理程序,如本例所示。然后,这些处理程序将从主线程自动调用。

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.

紫竹語嫣☆ 2024-10-13 14:27:59

你真的不应该这样做——UI 只能由主线程更新。

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

浅唱々樱花落 2024-10-13 14:27:59

您不能分配主窗体线程的面板,因为更新它不是线程安全的。线程可以通过Windows消息与应用程序线程(主窗体)通信,或者必须使用消息队列。
检查 OmniThreadLibrary 以简化您的工作。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文