Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
ВнизКак правильно блокировать/разблокировать поток? Найти похожие ветки
← →
DevilDevil © (2007-11-07 08:22) [0]Я не совсем о критических секциях говорю.
Известно, что поток должен простаивать относительно длительное время. Как правильнее реализовать Lock/UnLock для потомка TThread ?
Заранее спасибо
← →
Anatoly Podgoretsky © (2007-11-07 08:27) [1]> DevilDevil (07.11.2007 08:22:00) [0]
Suspend
← →
Сергей М. © (2007-11-07 08:35) [2]
> Известно, что поток должен простаивать относительно длительное
> время
Откуда дровишки ? ОБС ?
← →
Slym © (2007-11-07 08:49) [3]while not Terminated do
begin
Event.ResetEvent;
Event.WaitFor(TimeOut);//или INFINITE
...
end;
procedure Thread.Up;
begin
Event.SetEvent;
end;
← →
Kolan © (2007-11-07 08:51) [4]
WaitForSngleObject
еще
← →
DevilDevil © (2007-11-07 08:52) [5]я в потоках пока мало разбираюсь...
простенький вопрос:TThread.Execute
выполняется только один раз в течение жизни потока ? Тогда как правильнее организовать цикл ?
получиться должон что то типа:procedure TMyThread.ThreadProc();
begin
// потоковая процедура, Updater.
end;
procedure TMyThread.Execute();
begin
while <условие> do
begin
if not FLocked then
ThreadProc();
end;
end;
← →
Kolan © (2007-11-07 08:54) [6]> получиться должон что то типа:
Да.
Классика:procedure TMyThread.Execute();
begin
while not Terminated do
begin
if not FLocked then
ThreadProc();
end;
end;
Только прочти что такое естьTerminated
в справке.
← →
Сергей М. © (2007-11-07 08:58) [7]
> Execute выполняется только один раз в течение жизни потока
> ?
Да.
> как правильнее организовать цикл ?
Критериев "правильности" не существует.
Все зависит от логики, требуемой к реализации в потоке.
← →
Slym © (2007-11-07 08:58) [8]
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;
← →
DevilDevil © (2007-11-07 08:59) [9]хорошо, как правильно изменять флаг
FLocked
, через криьическую секцию ?
наверняка что-то типаSuspend/Resume
навесить, чтобы поток не тратил процессорного времени ?
← →
Slym © (2007-11-07 09:04) [10]DevilDevil © (07.11.07 8:59) [9]
Suspend/Resume
Это не правильно, поток должен сам остановиться на блокирующей функции (например Event.WaitFor)
Мой вариант чем не нравится?
← →
MBo © (2007-11-07 09:07) [11]Опиши задачу
← →
DevilDevil © (2007-11-07 09:14) [12]нравится. )
такой вопрос... корректна ли будет работа после:procedure Thread.Unlock;
begin
Event.SetEvent;
Event.SetEvent;
end;
илиprocedure Thread.Lock;
begin
Event.ResetEvent;
Event.ResetEvent;
end;
проще говоря, корректна ли будет выполняться работа при неоднократном вызовеLock()
илиUnLock()
?
Ну и вопрос напоследок.
Какие проблемы могут меня ожидать при вызове деструктора?
ну не забыть UnLock например, может с критическими секциями проблемы и т.д. ?
← →
DevilDevil © (2007-11-07 09:20) [13]Такой ещй маленький вопрос... много ли процессорного времени кушает
Event.WaitFor()
, есть ли способ экономичней, стоит ли вообще париться ?
← →
DevilDevil © (2007-11-07 09:42) [14]Задача - проигрывание звука.
Есть объект - Плеер, который хранит в себеSoundBuffer
иThread
.
Поток должен заполнятьSoundBuffer
данными, но может и не заполнять (простаивать), если Плейер находится в состоянии паузы или стопа. Доступ к буфферу и некоторым данным должен быть синхронизируемым.
← →
Kolan © (2007-11-07 09:42) [15]> стоит ли вообще париться
Не стоит.
← →
Сергей М. © (2007-11-07 09:52) [16]
> DevilDevil © (07.11.07 09:42) [14]
Синхронизация доступа к буферу - с пом. крит.секции.
Управление работой потока - с пом. сообщений или системных объектов синхронизации (ивент, мьютекс), можно и крит.секцию прикрутить.
В первом приближении считай, что поток, находящийся в kernel-time, процессорное время не потребляет. Перевод потока в kernel-time осуществляется вызовами ф-ций ожидания - [Msg]WaitForXXXXXX, Wait/GetMessage.
← →
DevilDevil © (2007-11-07 10:19) [17]спасибо.
как правильно оформить деструктор? так пойдёт: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
, то подождать завершения этой функции.
← →
Kolan © (2007-11-07 10:25) [18]> 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:42) [19]1)
FreeOnTerminate
- хорошее замечание
2) почемуWhile True Do
не прокатит, там же есть проверка наTerminated
?
3) в остальном то всё правильно ?
← →
Slym © (2007-11-07 11:02) [20]Из прочитаного формализую задачу:
Необходим потокозащищенный объект-буфер с 1 входом (write) и 1 выходом (read), при попытке чтения из пустого буфера читающий поток должен быть остановлен до появления в буфере данных, и пишуший поток должен быть остановлен при попытке писать в заполненный буфер...
для всего этого прекрасно подходит анонимный пайп CreatePipe
← →
umbra © (2007-11-07 11:20) [21]
> почему While True Do не прокатит, там же есть проверка на
> Terminated ?
прокатит, конечно. просто есть люди, которых бесят циклы видаwhile true do .....
но я бы сделал проверку на Terminated в самом начале
← →
DevilDevil © (2007-11-07 11:42) [22]> 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)
поток только пишет. но может быть так же в заблокированном состоянии.
← →
Slym © (2007-11-07 11:55) [23]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:57) [24]и ещё вопрос: процедуры
Lock()
иUnLock()
могут вызываться из обоих потоков; процедуры надо защищать критической секцией ?
← →
umbra © (2007-11-07 12:04) [25]а зачем в деструкторе вообще писать
Terminated := true;
, если он вызовется только после того, как свойствуTerminated
присвоят значениеtrue
?
← →
Сергей М. © (2007-11-07 12:06) [26]//обработчик сообщения TM_PLAY
FPlayState := psPlay;
while not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) do
DoSomething(..);
//обработчик сообщения TM_PAUSE
FPlayState := psPause;
//обработчик сообщения TM_STOP
FPlayState := psStop;
//основной цикл поточной процедуры
while not Terminated and GetMessage(Msg, 0, 0, 0) do
Dispatch(Msg.message);
← →
DevilDevil © (2007-11-07 12:58) [27]> umbra © (07.11.07 12:04) [25]
разве ?
а если я из основного потока вызовуThread.Free
?
> Сергей М. © (07.11.07 12:06) [26]
имхо кривовато. может через критическую секцию ?
← →
Сергей М. © (2007-11-07 13:03) [28]
> DevilDevil © (07.11.07 12:58) [27]
> может через критическую секцию ?
>
Вот ее как раз и используй в теле DoSomething.
А на этом примере я показал один из вариантов управления потоком.
← →
umbra © (2007-11-07 13:09) [29]
> а если я из основного потока вызову Thread.Free ?
>
если делать так, то не вижу смысла в строкеFreeOnTerminate := True;
Лучше вызовитеThread.Terminate
:)
← →
DevilDevil © (2007-11-07 13:09) [30]вобщем, ладно.
я и так многое узнал, полученных знаний скорее всего хватит.
в случае чего ещё раз приду с возгласами "спасите-помогите !!!"
Участникам большое спасибо !
← →
DevilDevil (2007-11-08 00:25) [31]мда... такой вопрос...
AccessViolation в библиотеке ntdll.dll при выполнении кода:procedure TMyClass.BeginCriticalSection();
begin
EnterCriticalSection(FCriticalSection);
end;
В конструктореTMyClass
вызываетсяZeroMemory(@FCriticalSection, sizeof(TRTLCriticalSection));
← →
Германн © (2007-11-08 00:34) [32]А что ты хотел поиметь вот тут
> @FCriticalSection
← →
DevilDevil (2007-11-08 00:46) [33]TRTLCriticalSection - структура, которую наверное как то надо инициализировать, которую возможно надо обнулять...
← →
Германн © (2007-11-08 01:00) [34]
> DevilDevil (08.11.07 00:46) [33]
>
> TRTLCriticalSection - структура, которую наверное как то
> надо инициализировать, которую возможно надо обнулять...
>
>
В Киеве бузина, а в огороде дядька.
Я тебя спрашивал про то, что по-твоему означает конструкция @FCriticalSection?
← →
KilkennyCat © (2007-11-08 01:02) [35]
> что по-твоему означает конструкция @FCriticalSection?
собака ф будке, которую пора отремонтировать, либо собака ф бешенстве.
← →
DevilDevil (2007-11-08 01:10) [36]> Германн © (08.11.07 01:00) [34]
я что-то недогоняю, к чему ты клонишь. Взятие указателя конечно.
А как ещё ты вызовешь ZeroMemory ?
← →
Германн © (2007-11-08 01:31) [37]
> DevilDevil (08.11.07 01:10) [36]
>
> > Германн © (08.11.07 01:00) [34]
>
> я что-то недогоняю, к чему ты клонишь. Взятие указателя
> конечно.
> А как ещё ты вызовешь ZeroMemory ?
>
1. Из справки:
VOID ZeroMemory(
PVOID Destination, // address of block to fill with zeros
DWORD Length // size, in bytes, of block to fill with zeros
);
Parameters
Destination
Points to the starting address of the block of memory to fill with zeros.
И ты решил, что @FCriticalSection даст тебе "адрес начала блока памяти"?
2. Из справки:
The @ operator returns the address of a variable, or of a function, procedure, or method; that is, @ constructs a pointer to its operand. For more information about pointers, see Pointers and pointer types. The following rules apply to @.
If X is a variable, @X returns the address of X.
Перевожу: @ оператор возвращает адрес самой переменной в памяти, а не адрес на который указывает её содержимое.
← →
Slym © (2007-11-08 06:16) [38]DevilDevil (08.11.07 0:25) [31]
ZeroMemory(@FCriticalSection, sizeof(TRTLCriticalSection));
а надо
InitializeCriticalSection(FCriticalSection)
← →
Сергей М. © (2007-11-08 10:25) [39]
> DevilDevil (08.11.07 00:25) [31]
Есть готовый класс для работы с крит.секцией - TCliticalSection.
Все что нужно - создать его экз-р и ссылку на него раздать всем заинтересованным в синхронизации потокам.
Вход в секцию - метод Enter, выход - Leave.
И незачем изобретать новый кривой велосипед)
← →
DevilDevil © (2007-11-08 15:01) [40]> Slym © (08.11.07 06:16) [38]
спасибо, что-то ступил, даже хелп не помотрел.
> Сергей М. © (08.11.07 10:25) [39]
тоже спасибо.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.042 c