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

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

Как усыпить поток. [D7, WinXP]


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

Kolan ©   (2006-02-06 21:50:00) 

Здравствуйте,
 Много раз слышал при обсуждении работы с потоками
"если то-то то поток засыпает, если еще что-то то просыпается..."

А как это. Можно пример усыпления.
Я просто проверяю какое-нибудь условие и если потоку делать нечего делаю например Sleep(1). А иначе загрузка процессора на 97% - 99%


Digitman   (2006-02-08 09:49:00) [41]


> отказываться от кольцевого буфера в принимающем потоке -
>  не стоит


Тогда потери пакетов не исключены.


Defunct   (2006-02-08 09:43:00) [42]


> Digitman ©   (08.02.06 09:20) [47]
> Если так, то использование массива в кач-ве очереди вряд ли оправдано.


нет, у него там немного иная задача.

Один поток обслуживает канальный уровень по приему пакетов от некоего устройства через COM порт. Второй поток должен обрабатывать уже готовые пакеты. Очередь (TQueue) можно использовать в качестве согласующего звена между первым и вторым потоком, но вот отказываться от кольцевого буфера в принимающем потоке - не стоит.


Digitman   (2006-02-08 09:20:00) [43]


> Kolan ©   (07.02.06 20:58) [45]


Насколько я понял, тебе требуется реализовать следующее :

Есть некая очередь данных, требующих обработки.
Один код.поток (1) помещает данные по мере их формирования в хвост очереди, другой код.поток (2) извлекает данные из головы очереди и обрабатывает их (либо "спит" если очередь пуста).

Если так, то использование массива в кач-ве очереди вряд ли оправдано.

Например, есть готовый класс TQueue, реализующий логику очереди. Можно защитить доступ к методам/св-вам его экз-ра крит.секцией, при добавлении в хвост очереди устанавливать событие (SetEvent), при опустошении очереди сбрасывать событие (ResetEvent).
Поток 1, добавляя очередной элемент (или несколько очередных элементов) в хвост, "сигналит" об этом установкой события. Поток 2 "просыпается" по этому сигналу и начинает циклически выбирать элементы из головы и обрабатывать их, до тех пор пока не обнаружит опустошение очереди, после чего вновь "засыпает", сбросив непосредственно перед этим событие в несигналящее состояние.


evvcom   (2006-02-08 08:39:00) [44]

Это же не весь код. AddArray только описан, но где вызывается не ясно. В коде доступ к FWriteIndex, FReadIndex осуществляется из всех этих 3-х методов. Execute и MakeAndSendPackage синхронизированы, а AddArray не ясно.
FWriteIndex <> FReadIndex - это тоже доступ.

> Те весь этот if надо зашитить?

Все зависит от того, синхронизированы ли уже доступы из разных потоков.


Kolan   (2006-02-07 20:58:00) [45]

Спасибо за ответ. Завтра разберусь....
:)


Defunct   (2006-02-07 19:30:00) [46]

> Kolan

Почитайте последний пост, в вашей предыдущей ветке.


Kolan   (2006-02-07 17:44:00) [47]

Я непонял
if (FState <> sIdle) and (FWriteIndex <> FReadIndex) then
Это же тоже доступ?
Те весь этот if надо зашитить?


Digitman   (2006-02-07 17:15:00) [48]


> Kolan ©   (07.02.06 16:46) [41]


Эта логика ведет к непредсказуемым (печальным) последствиям...

Доступ к массиву и тем самым индексам в нем должен быть защищен крит.секцией.


Kolan   (2006-02-07 16:46:00) [49]

Индыксы обнулятся только если состояние sIdleи доп поток гарантированно не использует эти переменные

Вообщем вот полный код:

procedure TPackageExtractThread.AddArray(Arr: array of Byte);
var
 I, J: Longint;
begin
 if FState = sIdle then
 begin
   FWriteIndex := 0;
   FReadIndex := 0;
 end;
 J := FWriteIndex;
 for I := Low(Arr) to High(Arr) do
 begin
   FBuffer[J] := Arr[I];
   J := J + 1;
 end;
 FWriteIndex := J;
 if FState = sIdle then
 begin
   FState := sWaitForStart;
 end;
end;


procedure TPackageExtractThread.Execute;
begin

 FreeOnTerminate := True;
 while not Terminated do
 begin
    if (FState <> sIdle) and (FWriteIndex <> FReadIndex) then
    begin
      case FState of
        sWaitForStart:
          begin
            if (FBuffer[FReadIndex] = StartByte) then
            begin
              FState := sWaitForEnd;
              FStartIndex := FReadIndex;
            end;
              FReadIndex := FReadIndex + 1;
           end;

        sWaitForEnd:
          begin
            if (FBuffer[FReadIndex] = EndByte) then
            begin
              FState := sEndFound;
            end;
            FReadIndex := FReadIndex + 1;
          end;

        sEndFound:
          begin
            if (FBuffer[FReadIndex] <> EndByte) then
            begin
              FState := sPackegeReady;
              FReadIndex := FReadIndex - 1;
            end
            else
            begin
              FState := sWaitForEnd;
            end;
            FReadIndex := FReadIndex + 1;
          end;

        sPackegeReady:
          begin
            FEndIndex := FReadIndex;
            FState := sIdle;
            Synchronize(MakeAndSendPackage);
          end;
      end;
    end
    else
    begin
      Sleep(1);
    end;
 end;
end;



procedure TPackageExtractThread.MakeAndSendPackage;
var
 I, J: Longint;
 Answer: array of Byte;
begin
 SetLength(Answer, (FEndIndex - FStartIndex) + 1);
 J := Low(Answer);
 for I := FStartIndex to FEndIndex do
 begin
   Answer[J] := FBuffer[I];
   J := J + 1;
 end;
 FState := sIdle;
 FReadIndex := 0;
 FWriteIndex := 0;
 FPackageReadyEvent(Self, Answer);
end;


Digitman   (2006-02-07 16:42:00) [50]


> А что будет ошибка если один поток сделает
> FWriteIndex := J;
> А второй в этоже время проверит
> if (FState <> sIdle) and (FWriteIndex <> FReadIndex) then
> ?


Бардак будет.


Kolan   (2006-02-07 16:40:00) [51]

Kolan ©   (07.02.06 14:19) [20]

Вопрос такой: Если я уже сделал SetEvent и сделаю ео повторно - что будет?

Я это не просто так спрашивал. Я сначала все позашишал кр. секциями...

Возникала сит когда я дважды делал Releaseи потом Acquireуже не вызывался. Как проверить тек сост кр. секции я ненашел...
Поэтому переделал без кс.

А что будет ошибка если один поток сделает
FWriteIndex := J;
А второй в этоже время проверит
if (FState <> sIdle) and (FWriteIndex <> FReadIndex) then
?


Digitman   (2006-02-07 16:36:00) [52]


> Когда поток нашел покет, он вызовет процедуру передач и
> пакета и обнулит индекс ы. Не пойму где они пересекутся



> Доп поток изменяет только индекс чтения


"Как тебя понимать, Саид ?" (с)


Kolan   (2006-02-07 16:32:00) [53]

Доп поток изменяет только индекс чтения. Гл поток изменяет индекс записи.
Причем если состояние Idle(те доп поток не работает) обнуляет индексы.

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

Или если один поток пишет по индексу A а второй по индексу B одного и тогоже массива(причем точно индексы разные) - будет ошибка?

Скажите - это может повлиять на правильность работы с Event. Те из - за чего межет засыпать...


evvcom   (2006-02-07 16:28:00) [54]


> Ведь записываю и читаю всегда по разным индексам

Ты сами переменные читаешь и пишешь в разных потоках, уже это надо синхронизировать.


Digitman   (2006-02-07 16:16:00) [55]


> Может я и неправ


с учетом


> изменяют их главный и доп поток


оч даже неправ !


Kolan   (2006-02-07 16:13:00) [56]

Да уж .. где синхронизация-то ? доступа к этим данным ?
Нету

Я думая она ненужна... Ведь записываю и читаю всегда по разным индексам...
Может я и неправ.

Вообщето она была, но я убрал ее...

А если Write на круг обогнал Read?
Нет такое невозможно... Если по идее до конца массива они не дойдут( если дойдут массив увеличу...)


Digitman   (2006-02-07 15:33:00) [57]


> Kolan ©   (07.02.06 15:00) [28]


Да уж .. где синхронизация-то ? доступа к этим данным ?


evvcom   (2006-02-07 15:09:00) [58]


> FReadIndex как бы догоняет FWriteIndex если они сравнялись,
>  то жду пока еще добавят байты

А если Write на круг обогнал Read?


evvcom   (2006-02-07 15:07:00) [59]


> Но изменяют их главный и доп поток...

Что-то в твоем коде синхронизации доступа к ним не видно... :( Очень подозрительна фраза "все работает"


Kolan   (2006-02-07 15:06:00) [60]

Извените, отвечу позже :)


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

Наверх

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