我有一个同时运行多个线程的程序。每个线程连接一个数据库并将数据从一个表传输到另一个表。现在我想为MainForm中的每个线程分配一个面板,这样如果连接成功,我可以将Panel的颜色更改为绿色,如果在重试多次后它被破坏,我可以将其更改为红色。
那么如何告诉一个线程哪个Panel是它自己的Panel?
答案 0 :(得分:10)
创建线程类时,将一个变量添加到商店面板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;
当你的线程需要更新面板上的数据时,它应该向主表单发送一个特别定义的消息:
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相同。
这里重要的是你不能也不应该尝试从主线程以外的线程更新可视组件。如果需要更新用户控件,则应将消息发布到主窗体并创建处理程序过程,如本例所示。然后将从主线程自动调用这些处理程序。
答案 1 :(得分:3)
你真的不应该这样做 - UI只应由主线程更新。
答案 2 :(得分:1)
您无法指定主窗体线程的面板,因为更新它不是线程安全的。线程可以通过Windows消息与应用程序线程(主窗体)通信,或者您必须使用消息队列。 检查OmniThreadLibrary以简化您的工作。