Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.10.07;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.079 c
2-1189575199
zero
2007-09-12 09:33
2007.10.07
Помогите решить задачку на турбо паскале


1-1185351667
Unknown user
2007-07-25 12:21
2007.10.07
Нейронные сети


15-1189094106
Ezorcist
2007-09-06 19:55
2007.10.07
portable delphi?


2-1189264124
AIK
2007-09-08 19:08
2007.10.07
Диспетчер задач


2-1189425493
Romm
2007-09-10 15:58
2007.10.07
Имя файла





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский