我有一个程序同时运行多个线程。每个线程连接一个数据库并将数据从一个表传输到另一个表。现在我想为MainForm中的每个线程分配一个面板,这样我可以在连接成功时将面板的颜色更改为绿色,或者在重试次数后断开面板的红色。为每个线程分配面板 - 德尔福
那么我怎么能告诉一个线程哪个面板是它自己的面板呢?
我有一个程序同时运行多个线程。每个线程连接一个数据库并将数据从一个表传输到另一个表。现在我想为MainForm中的每个线程分配一个面板,这样我可以在连接成功时将面板的颜色更改为绿色,或者在重试次数后断开面板的红色。为每个线程分配面板 - 德尔福
那么我怎么能告诉一个线程哪个面板是它自己的面板呢?
当你创建一个线程类,添加一个变量来存储面板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;
对于每一个线程创建面板,并设置它的标记值这个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。
这里最重要的是你不能尝试从主线程以外的线程更新可视化组件。如果您需要更新用户控件,则应将消息发布到主窗体并创建处理程序过程,如本例中所示。这些处理程序过程将被主线程自动调用。
你真的不应该这样做 - UI只应该由主线程更新。
我,我会有一个主窗体数组来关联线程和面板。然后是一个读取线程状态并更新适当面板的计时器。这样线程就可以完成任务,并且可以随时更改UI,而无需执行任何操作。 – mj2008 2010-12-08 10:17:47
您不能分配主窗体线程的面板,因为它不是线程安全的以更新它。该线程可以通过Windows消息与应用程序线程(主窗体)交流,或者您必须使用消息队列。 检查OmniThreadLibrary以简化您的工作。
正如我所记得的,Synchronize()是Borland为这种事情设计的。 – 2010-12-07 15:24:08