我想刷新Treenode.text(使用已用时间)并使用来自同一线程的计时器。正如我读到它不建议在一个线程中使用TTimer *,但那么,使用什么呢?谢谢。
*我想使用一些时间而不是睡眠()。不只是因为那些俗气(?),但我必须,因为否则我只能在每一秒刷新treenodetext。)>>
unit master_slave
...
Tsrch_slave_thread = class(TThread)
protected
procedure Execute; override;
public
master: TMaster;
end;
TMaster = class(TObject)
private
...
FMasterNode: TTreeview;
Fsw: TStopWatch;
Fslave_search_thread : Tsrch_slave_thread;
...
end;
...
implementation
...
procedure Tsrch_slave_thread.Execute;
var
searchactive: integer;
begin
while not terminated do begin
searchactive := master.CMD_LISTCNT
if searchactive = 1 then //(master.CMD_LISTCNT's return value = 1, if master finished search on the bus)
exit;
sleep(1000); //dont want to flood the master with UDP packets... (master.CMD_LISTCNT sends UDP packets)
synchronize(procedure begin
with FmasterNode do
text := text + floattostr(Fsw.ElapsedMilliseconds / 1000);
end);
end;
end;
答案 0 :(得分:4)
而不是Sleep(1000)
,请使用可等待的事件。
例如TSimpleEvent
。
FMySimpleEvent.WaitFor(1000);
如果您想提前退出该帖子,请覆盖TThread.DoTerminate
方法并致电:
FMySimpleEvent.SetEvent;
这样的事情:
procedure Tsrch_slave_thread.Execute;
var
searchactive: integer;
begin
while not terminated do begin
searchactive := master.CMD_LISTCNT
if searchactive = 1 then (master.CMD_LISTCNT's return value = 1, if search finished)
exit;
if (FMySimpleEvent.WaitFor(1000) = wrTimeOut) then
synchronize(procedure begin
with FmasterNode do
text := text + floattostr(Fsw.ElapsedMilliseconds / 1000);
end);
end;
end;
procedure Tsrch_slave_thread.DoTerminate;
begin
Inherited;
FMySimpleEvent.SetEvent;
end;
答案 1 :(得分:0)
您可以在线程中使用计时器,而不是TTimer
。你必须根据SetTimer
制作自己的。而且您还需要创建自己的窗口来处理消息,因为您无法在线程中使用AllocateHWnd
。现在,如果你知道你不会显示任何模态对话框或运行任何模态大小调整循环或模态菜单循环,那么你可以使用无窗口计时器。
但这一切都迫使你在你的线程中实现一个消息循环。这增加了另一层复杂性。在后台线程中实现计时器是阻塞方法合理的少数几种情况之一。我建议你采用这种方法。
如果您的间隔足够短,那么您可以使用Sleep
。缺点是您需要等待调用Sleep
才能终止线程。因此,对于更长的间隔,这可能是一个问题。
如果您希望能够立即终止,您可以使用Sleep
或{{1}中定义的某个事件类,而不是使用WaitForSingleObject
,等待超时事件。单位。如果超时,则计时器已经过去。如果事件已发出信号,那么您的线程将被终止。