Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.047 c
2-1194626179
asd00
2007-11-09 19:36
2007.12.02
как с эмитировать нажатие правой/левой кнопки мыши?


15-1193901205
Slider007
2007-11-01 10:13
2007.12.02
С днем рождения ! 1 ноября 2007 четверг


15-1193748220
Sairex
2007-10-30 15:43
2007.12.02
Подкиньте ссылку на документацию по iphlpapi.dll


15-1193625473
Фар-юзер
2007-10-29 05:37
2007.12.02
FAR открыл исходники !


2-1194260692
Петрович07
2007-11-05 14:04
2007.12.02
вопрос по циклу,условию





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский