Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как правильно блокировать/разблокировать поток?


Страницы:   1 2 3

DevilDevil ©   (2007-11-07 08:22:00) 

Я не совсем о критических секциях говорю.
Известно, что поток должен простаивать относительно длительное время. Как правильнее реализовать Lock/UnLock для потомка TThread ?

Заранее спасибо


DevilDevil   (2007-11-07 11:57:00) [21]

и ещё вопрос: процедуры Lock()и UnLock()могут вызываться из обоих потоков; процедуры надо защищать критической секцией ?


Slym   (2007-11-07 11:55:00) [22]

DevilDevil ©   (07.11.07 9:42) [14]
Доступ к буфферу и некоторым данным должен быть синхронизируемым

Необходим потокозащищенный объект-буфер с 1 входом (write) и 1 выходом (read)...
Есть как минимум 2 потока: 1 играющий звук - он делает из SoundBuffer чтение read; второй поток заполняет SoundBuffer т.е. делает ему Write
DevilDevil ©   (07.11.07 9:42) [14]
Поток должен заполнять SoundBuffer данными, но может и не заполнять (простаивать),

пишуший поток должен быть остановлен при попытке писать в заполненный буфер...
а играющий поток при попытке чтения из пустого буфера читающий поток должен быть остановлен до появления в буфере данных


DevilDevil   (2007-11-07 11:42:00) [23]

> umbra ©   (07.11.07 11:20) [21]

представим ситуацию: на момент деструктора поток был в режиме Lock(), т.е. " Нельзя вызывать функцию OnThreadProc". Мы пишем:
  Terminated := true;
  UnLock();
  Event.Free;


если не ставить условие после WaitFor(), то выполнится функция OnThreadProc, чего делать нельзя!

> Slym ©   (07.11.07 11:02) [20]
ээээ...... слишком много букав и слов сложных О_о?

не совсем понял, что такое объект-буфер с 1 входом (write) и 1 выходом (read)
поток только пишет. но может быть так же в заблокированном состоянии.


umbra   (2007-11-07 11:20:00) [24]


> почему While True Do не прокатит, там же есть проверка на
> Terminated ?

прокатит, конечно. просто есть люди, которых бесят циклы вида

while true do .....

но я бы сделал проверку на Terminated в самом начале


Slym   (2007-11-07 11:02:00) [25]

Из прочитаного формализую задачу:
Необходим потокозащищенный объект-буфер с 1 входом (write) и 1 выходом (read), при попытке чтения из пустого буфера читающий поток должен быть остановлен до появления в буфере данных, и пишуший поток должен быть остановлен при попытке писать в заполненный буфер...
для всего этого прекрасно подходит анонимный пайп CreatePipe


DevilDevil   (2007-11-07 10:42:00) [26]

1) FreeOnTerminate- хорошее замечание
2) почему While True Doне прокатит, там же есть проверка на Terminated?
3) в остальном то всё правильно ?


Kolan   (2007-11-07 10:25:00) [27]

> WHILE TRUE DO

тАК ТОЧНО НЕ ПОЙДЕТ

И потом У тя поток вечно жить будет чтоли?

procedure TMusicPlayerThread.Execute;
begin
FreeOnTerminate := True;
WHILE not Terminated DO
BEGIN
    Event.WaitFor(INFINITE); //Locked ?
    if Terminated then break;

    try
       FPlayer.BeginCriticalSection();
       FPlayer.OnThreadProc;
    finally
       FPlayer.EndCriticalSection();
    end;

END;
end;


DevilDevil   (2007-11-07 10:19:00) [28]

спасибо.

как правильно оформить деструктор? так пойдёт:

procedure TMusicPlayerThread.Execute;
begin
 WHILE TRUE DO
 BEGIN
     Event.WaitFor(INFINITE); //Locked ?
     if Terminated then break;

     try
        FPlayer.BeginCriticalSection();
        FPlayer.OnThreadProc;
     finally
        FPlayer.EndCriticalSection();
     end;

 END;
end;

destructor TMusicPlayerThread.Destroy();
begin
   Terminated := true;
   UnLock();
   Event.Free;

   inherited;
end;


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


Сергей М.   (2007-11-07 09:52:00) [29]


> DevilDevil ©   (07.11.07 09:42) [14]


Синхронизация доступа к буферу - с пом. крит.секции.

Управление работой потока - с пом. сообщений или системных объектов синхронизации (ивент, мьютекс), можно и крит.секцию прикрутить.

В первом приближении считай, что поток, находящийся в kernel-time, процессорное время не потребляет. Перевод потока в kernel-time осуществляется вызовами ф-ций ожидания - [Msg]WaitForXXXXXX, Wait/GetMessage.


Kolan   (2007-11-07 09:42:00) [30]

> стоит ли вообще париться

Не стоит.


DevilDevil   (2007-11-07 09:42:00) [31]

Задача - проигрывание звука.
Есть объект - Плеер, который хранит в себе SoundBufferи Thread.
Поток должен заполнять SoundBufferданными, но может и не заполнять (простаивать), если Плейер находится в состоянии паузы или стопа. Доступ к буфферу и некоторым данным должен быть синхронизируемым.


DevilDevil   (2007-11-07 09:20:00) [32]

Такой ещй маленький вопрос... много ли процессорного времени кушает Event.WaitFor(), есть ли способ экономичней, стоит ли вообще париться ?


DevilDevil   (2007-11-07 09:14:00) [33]

нравится. )
такой вопрос... корректна ли будет работа после:
procedure Thread.Unlock;
begin
Event.SetEvent;
Event.SetEvent;
end;


или

procedure Thread.Lock;
begin
Event.ResetEvent;
Event.ResetEvent;
end;


проще говоря, корректна ли будет выполняться работа при неоднократном вызове Lock()или UnLock()?

Ну и вопрос напоследок.
Какие проблемы могут меня ожидать при вызове деструктора?
ну не забыть UnLock например, может с критическими секциями проблемы и т.д. ?


MBo   (2007-11-07 09:07:00) [34]

Опиши задачу


Slym   (2007-11-07 09:04:00) [35]

DevilDevil ©   (07.11.07 8:59) [9]
Suspend/Resume

Это не правильно, поток должен сам остановиться на блокирующей функции (например Event.WaitFor)
Мой вариант чем не нравится?


DevilDevil   (2007-11-07 08:59:00) [36]

хорошо, как правильно изменять флаг FLocked, через криьическую секцию ?
наверняка что-то типа Suspend/Resumeнавесить, чтобы поток не тратил процессорного времени ?


Slym   (2007-11-07 08:58:00) [37]

uses SyncObjs;
type
TMyThread=class(TThread)
private
 Event:TSimpleEvent;
...

procedure TMyThread.ThreadProc();
begin
 // потоковая процедура, Updater.
end;

procedure TMyThread.Execute();
begin
while not Terminated do
begin
 Event.WaitFor(INFINITE);
 ThreadProc;
end;
end;

procedure Thread.Unlock;
begin
 Event.SetEvent;
end;

procedure Thread.Lock;
begin
 Event.ResetEvent;
end;


Сергей М.   (2007-11-07 08:58:00) [38]


> Execute выполняется только один раз в течение жизни потока
> ?


Да.


> как правильнее организовать цикл ?


Критериев "правильности" не существует.
Все зависит от логики, требуемой к реализации в потоке.


Kolan   (2007-11-07 08:54:00) [39]

> получиться должон что то типа:

Да.

Классика:
procedure TMyThread.Execute();
begin
while not Terminated do
begin
     if not FLocked then
       ThreadProc();
end;
end;


Только прочти что такое есть Terminatedв справке.


DevilDevil   (2007-11-07 08:52:00) [40]

я в потоках пока мало разбираюсь...

простенький вопрос: TThread.Executeвыполняется только один раз в течение жизни потока ? Тогда как правильнее организовать цикл ?

получиться должон что то типа:

procedure TMyThread.ThreadProc();
begin
  // потоковая процедура, Updater.
end;

procedure TMyThread.Execute();
begin

 while <условие> do
 begin
      if not FLocked then
        ThreadProc();
 end;

end;


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо