Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Проблема с потоками


Автор: krik 17.11.2008, 00:04
Всем привет! Столкнулся с проблемой в потоках. Вообщем есть программа. В ней создаются 5 экземпляров класса потока. Сначало запускается первый экземпляр, который выполняет (как и все остальные) простую операцию инкрементирования переменной и выводит её в стринг гирд. После того как нажата кнопка, либо пройдёт время (например 2 секнунды) запускается следующий (2) экземпляр, а первый ставиться на паузу так сказать. Так продолжается пока не достигает до 5 последнего потока, после него должн быть запущен снова 1 по списку экземпляр. Проблема заключается в том, что пройдя первый круг, не запускается снова первый экзепляр. Незнаю испробовал много, но чёт не получается. Кстати вообще это реализация карусельной многозадачности (round robin) по теме диспечеризация потоков. Кто сможет помочь - проект приложен! Заранее благодарю!

Автор: ReInit 17.11.2008, 06:18
Код

procedure TMyThread.Execute;
begin
  inherited;
  time:=now;
  While (Suspended = false) and (MilliSecondsBetween(Time,Now)<1000) do
    begin
      AddNumber;
      Synchronize(self.PrintResult);
    end;
  Synchronize(self.Proc);
end;

что-то мне подсказывает, что по прошествии 1000 мсек поток успешно завершится и делать
Код

Thread[ActiveThread].Resume;

уже бесполезно...

Автор: krik 17.11.2008, 09:22
Что же тогда посоветуете для реализации поставленой задачи? Тут принципе задача то остаётся нерешёной. Нада сделать чтобы поток работал определённое время, после чего приостанваливался и когда очередь доходила до него опять запускался, но как это реализовать, так и не нашёл

Автор: REZiaMIX 17.11.2008, 09:37
Цитата(krik @ 17.11.2008,  09:22)
Что же тогда посоветуете для реализации поставленой задачи? Тут принципе задача то остаётся нерешёной. Нада сделать чтобы поток работал определённое время, после чего приостанваливался и когда очередь доходила до него опять запускался, но как это реализовать, так и не нашёл

Могу предложить алгоритм:
В цикле:
1)Создаем поток
2)WaitForSingleObject для потока
3)goto 1

а сколько раз выполнять цикл - решение Ваше)

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

Автор: ReInit 17.11.2008, 16:57
Они вручную должны переключатся кнопкой или офтомотически друг за другом?
Если превое, то что-то типа этого
Код

procedure TMyThread.Execute;    
begin    
inherited;
while true do 
  begin
  Inc(self.FNumber);
  Synchronize(self.PrintResult);    
  end;
Synchronize(self.Proc);
end;


И почему у тебя time - глобальная?

Автор: krik 17.11.2008, 19:54
Вообщем проблему решил, были проблемы в логике программы, да и таймер это точно был гон. А задача была и чтобы само приостанваливалось через какой-то промежуток времени и если нажата кнопка то независимо от того прошёл ли период времени.

Автор: krik 13.2.2009, 17:31
Ну вот и снова я, думаю не стоит создавать новую тему. При решении диспетчеризации потоков произошла проблема. У меня есть программка реализующая метод FIFO, но дело в том, что если я запускаю её на слабых компах, получается так, что поток не успевает остановиться (скорей всего) и выдаётся ошибка. 

Код

procedure TForm1.Button2Click(Sender: TObject); 
begin
  Thread[ActiveThread].Suspend;//>>>>>>>>>>>>>>>>>тут приостановка 
  Inc(ActiveThread);
  if (ActiveThread = 5) then ActiveThread := 0;
  Thread[ActiveThread].Resume;//
end;


Пример программки в архиве.

Кто что посоветовать может по этому поводу? Думаю если не тут, то уверен что больше не кто не поможет. 

Автор: krik 14.2.2009, 11:12
Разве ни кто не сталкивался с этим? Да, забыл сказать что появляется ошибка "Thread Error: Отказано в доступе (5)"

Автор: krik 15.2.2009, 12:11
Люди! Ну очень прошу помочь, перепробовал много, но не могу найти решение ((((((

Автор: MetalFan 15.2.2009, 12:35
дааа... статейку про потоки неплохо былоб прочитать.
1. Нет смысла в TMyThread.Execute вызывать inherited.
2. Не корректно из кода самого потока проверять флаг Suspended... и вообще Suspend/Resume не самый лучший вариант для реализации задачи приостановки выполнения кода потока...
3. Да и вообще код потока-бредовый...

Автор: krik 15.2.2009, 15:21
2MetalFan чтобы ты посоветовал на счёт 2 пункта?

Автор: MetalFan 15.2.2009, 15:33
могу посоветовать поковырять юнит SyncObjs. например обертку над Event'ами TEvent.
создаешь в конструкторе потока TEvent с InitialState = false. в execute в цикле проверяешь состояние евента (WaitFor с небольшим временем ожидания), если Signaled - то выполняешь нудное действие.
соотв когда снаружи надо "активировать" трэд, вызываешь TMyThread.FEvent.SetEvent. 
только цикл в execute тоже надо правильно написать с учетом проверки флага Terminated... а то получишь "неубиваемый" поток.

Автор: krik 16.2.2009, 18:03
Т.е. к примеру получается если Signaled,  то разрушаем поток и запускаем следующий, при этом вся проверка должна проходить в Ехеcute? Спрашиваю это потому, что FreeOnTerminate в этом случае не поможет. Вот для примера, если я понял так должно быть?
Код

procedure TSimpleThread.Execute;
begin
  ev := TEvent.Create(nil,true,false,'test');
    repeat
      ev.ReSetEvent;
      res := ev.WaitFor(10);
      Synchronize(ShowInfo);
      if integer(res)=0 then
          Terminate;
    until Terminated;
  ev.Free;
end;

Автор: MetalFan 16.2.2009, 20:17
а зачем пересоздавать потоки???

Автор: krik 17.2.2009, 19:00
>>>и вообще Suspend/Resume не самый лучший вариант для реализации задачи приостановки выполнения кода потока...

Ты же сам написал

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)