![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно блокировать/разблокировать поток?
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;