Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.07;
Скачать: CL | DM;

Вниз

TThread ы и проблемы с ними же   Найти похожие ветки 

 
Mitrofan   (2007-07-24 01:51) [0]

Доброй ночи, коллеги.
Не пойму почему виснет следующий код.
 
TaskThread = class(TThread)
 private
 protected
   procedure Execute; override;
 public
   ThreadNumber: Integer;
   i1,i2: Integer;
end;

var
 threads: array [0..1] of TaskThread;
 events: array [0..1] of TEvent;

procedure TaskThread.Execute;
var s: Double;
   i: Integer;
begin
 FreeOnTerminate:=true;
 repeat
   for i:=i1 to i2 do begin

   end;
   events[ThreadNumber].SetEvent;
   Suspend;
 until Terminated;
end;

procedure TForm1.Button1Click(Sender: TObject);
const N = 2000;
var K, i, middle: Integer;
   t0,t1: Cardinal;
begin
 Randomize;
 threads[0]:=TaskThread.Create(true);
 threads[0].ThreadNumber:=0;
 events[0]:=TEvent.Create(nil, true, true, "");

 threads[1]:=TaskThread.Create(true);
 threads[1].ThreadNumber:=1;
 events[1]:=TEvent.Create(nil, true, true, "");

 K:=10000;
 t0:=GetTickCount;
 for i:=0 to N do begin
   middle:= (K div 2) - 1;

   threads[0].i1:=0;
   threads[0].i2:=middle;
   events[0].ResetEvent;

   threads[1].i1:=middle+1;
   threads[1].i2:=K-1;
   events[1].ResetEvent;

   threads[0].Resume;
   threads[1].Resume;

   events[0].WaitFor(INFINITE);
   events[1].WaitFor(INFINITE);
 end;
 t1:=GetTickCount;

 threads[0].Terminate;
 threads[1].Terminate;

 ShowMessage("Ok "+IntToStr(t1-t0));

Идея очень простая. Создаются две нити в программе.
Затем в цикле распределяется равномерно на них некоторый объем вычислений. После выполнения которого нить засыпает, до того момента пока ее не разбудять для обработки следующей порции данных. И так в цикле продолжается.
Подскажите, в чем я не прав. Запускаю на двухядерном ноутбуке и все ... виснет...


 
Сергей М. ©   (2007-07-24 08:34) [1]

Что показывает отладчик ?


 
sniknik ©   (2007-07-24 09:07) [2]

это не проблемы с потоками, это проблемы с логикой...

линейное программирование не совместимо с "событийным"... а у тебя именно линейное, вся "программа" в один столбик. в цикле стоит бесконечное ожидание события... и удивление а почему дальше то не проходит, виснет?
а вот потому, не делается так. вообще просто вставить потоки в программу это не панацея, нужно вставлять к месту и со знанием дела, как это работает... чтобы знать нужно предварительно почитать чего нибудь, а не просто писать абы что (просто набор операторов), и после в форум "помогите не работает", а и не должно при таком подходе.

> Запускаю на двухядерном ноутбуке и все ... виснет...
да хоть на 4-8-х ядерном, это не устраняет безграмотности. книги вот что поможет (не все правда... вспоминая Фленова и Архангельского... ;).


 
Однокамушкин   (2007-07-24 11:00) [3]

На очередной итерации цикла у вас в главной нити threads[N].Resume может выполниться раньше, чем в соответствующей нити выполнится suspend... Для простоты предположим, что у нас только одна нить TaskThread, а не две... В общем, представьте ситуацию: главная нить висит на WaitFor, тут событие происходит, неглавная нить теряет квант времени, его получает главная, выходит из WaitFor, идёт на начало цикла, выполняет назначения, вызывает threads[0].Resume, снова доходит до WaitFor и переходит в режим ожидания... Квант времени снова переходит неглавной нити, а она только-только вышла из events[ThreadNumber].SetEvent, дальше она выполняет Suspend и тоже переходит в режим ожидания... всё, дедлок, обе нити висят и каждая ждёт сигнала от другой...


 
Mitrofan   (2007-07-24 11:14) [4]

Хорошо, в таком случае как следует поступить ?
Как вы посоветуете организовать логику работы ?
Задача поста - нужна распараллелить цикл по количеству нитей
for i:=0 to N do begin
...
end.


 
Однокамушкин   (2007-07-24 11:18) [5]


> Mitrofan   (24.07.07 11:14) [4]
> Хорошо, в таком случае как следует поступить ?

Отказаться от Suspend/Resume, а тоже будить нить по событию - даже если в главной нити SetEvent будет вызван раньше, чем WaitFor в неглавной, проблем не возникнет...


 
Сергей М. ©   (2007-07-24 11:48) [6]

TTaskData = тип данных для обработки;
TTaskResult = тип результата обработки;

TNewTaskEvent = procedure(Sender: TObject; var Data: TTaskData; var HasData: Boolean) of object;

TTaskResultEvent = procedure(Sender: TObject; Data: TTaskResult) of object;

TTaskThread = class(TThread)
private
  FGetTask: TNewTaskEvent;
  FDone: TTaskResultEvent;
  FHasData: Boolean;
  FData: TTaskData;
  FResult: TTaskResult;
  procedure DoNewTask;
  procedure DoTaskResult;
protected
  procedure Execute; override;
public
  constructor Create(OnGetTask: TNewTaskEvent; OnDoneTask: TTaskResultEvent);
end;

constructor TTaskThread.Create(OnGetTask: TNewTaskEvent; OnDone: TTaskResultEvent);
begin
  FGetTask := OnGetTask;
  FDone := OnDoneTask;
  inherited Create(False);
end;

procedure TTaskThread.DoNewTask;
begin
 FHasData := False;
 FGetTask(Self, FData, FHasData);
 if not FHasData then Terminate;
end;

procedure TTaskThread.DoTaskResult;
begin
 FDone(Self, FResult);
end;

procedure TTaskThread.Execute;
begin
FreeOnTerminate:=true;
while not Terminated do begin
  Synchronize(DoNewTask);
  if Terminated then Exit;
... обработка данных, указанных в FpData
... формирование результата обработки в FResult
  Synchronize(DoTaskResult);
end;


 
Сергей М. ©   (2007-07-24 12:08) [7]

TForm1 = class(TForm)
..
procedure DoNewTask(Sender: TObject; var Data: TTaskData; var HasData: Boolean);
procedure DoTaskResult(Sender: TObject; Data: TTaskResult);
..

end;

procedure TForm1.DoNewTask;
begin
 if ЕстьНовыеЗадания then
   Data := ...данные для обработки потоком Sender
   HasData := True;
 end;
end;

procedure TForm1.DoTaskResult;
begin
 ..  в Data - результаты выполнения задания потоком Sender  ..
end;



Страницы: 1 вся ветка

Текущий архив: 2007.10.07;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.022 c
2-1189435060
qaPavel
2007-09-10 18:37
2007.10.07
MessageBox +отрисовка


2-1189192349
Tack
2007-09-07 23:12
2007.10.07
Выйти из программы после создания главной формы перед ее показом


6-1170620768
alexm_hs
2007-02-04 23:26
2007.10.07
Проблемы с вызовом XcvDataW


2-1189472253
Glivera
2007-09-11 04:57
2007.10.07
экземпляр формы


2-1189583797
Washington
2007-09-12 11:56
2007.10.07
В чём ошибка?