2014-02-14 3 views
2

Я хотел бы обновить Treenode.text (с истекшим временем) и использовать таймер из того же потока. Поскольку я читал его, не рекомендую использовать TTimer * в потоке, но потом, что использовать вместо этого? Спасибо.Синхронизация и синхронизация VCL (в/из потока)

* Я хочу использовать некоторое время вместо сна(). Не только потому, что то будет сырный (?), Но я должен, потому что в противном случае я могу обновить 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; 

ответ

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; 
+0

+1. Это правильный способ обработки ожиданий при выполнении определенного действия. 'Sleep' или таймеры должны использоваться только для обработки чего-либо, основанного на * определенном времени *; при ожидании на дискретном событии используйте ожидаемый сигнал. –

+0

@Mason этот код ждет определенный период времени –

+0

@LU RD, Спасибо. (Почему я не могу позвонить бесплатно на TStopWatch?) – grinner

0

Вы можете использовать таймер в потоке, просто не TTimer. Вы должны сделать свой собственный на основе SetTimer. И вам также нужно создать собственное окно для обработки сообщений, потому что вы не можете использовать AllocateHWnd в потоке. Теперь, если вы знаете, что не будете показывать какие-либо модальные диалоги или запускать любые модальные циклы размеров или модальные циклы меню, вы можете использовать таймер без окон.

Но все это заставляет вас реализовать цикл сообщений в вашем потоке. Что добавляет еще один уровень сложности. Реализация таймера в фоновом потоке является одним из немногих сценариев, когда подход блокировки является разумным. Я предлагаю вам принять этот подход.

Если ваш интервал достаточно короткий, вы можете использовать Sleep. Недостатком является то, что вам нужно дождаться вызова до Sleep, чтобы вернуться до того, как поток может быть прерван. Так что это может быть проблемой для более длинных интервалов.

Если вы хотите, чтобы иметь возможность завершить мгновенно вы можете вместо Sleep, ждать события с тайм-аутом, используя WaitForSingleObject, или один из классов событий, определенных в SyncObjs блоке. Если тайм-аут истекает, истечет ваш таймер. Если событие сигнализируется, то ваш поток, как ожидается, прекратится.

+0

Требуется использовать таймер, потому что путь я могу обновить treenode меньше секунды, но это действительно бесполезно. Остается с FMySimpleEvent.WaitFor или sleep(). Спасибо. – grinner

+0

Сон, таймеры и события имеют одинаковое разрешение. Все могут иметь частоту, большую, чем 1 Гц. –

+0

Да, но я должен оставить его на 1сек, потому что я не хочу посылать udp-пакеты чаще. Первоначальная идея заключалась в следующем: Отправить udp-пакеты только через каждые 1 сек, но обновить treenode.text, если говорить каждые 10 мс. – grinner

Смежные вопросы