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

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

access violation при работе с потоками


Valdis ©   (2013-07-17 19:18:00) 

Я тренируюсь работать с потоками для параллельных вычислений и столкнулся со следующей проблемой.Это просто пример:

Необходимо создать два потока, которые берут массив из основной части программы, делуют некие преобразования над его элементами и возвращают эти преобразованные элементы обратно в программу:

unit Unit1;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
 TForm1 = class(TForm)
   Memo1:TMemo;
   Button1:TButton;
   procedure Button1Click(Sender:TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

TStrAr = array[1..10]of integer;

TCalcThread = class(TThread)
private
FIsDone:Boolean;
FA,FB:TStrAr;
public
constructor Create(A:TStrAr); virtual;
property IsDone:Boolean read FIsDone;
property A:TStrAr read FA;
property B:TStrAr read FB;
end;

T1st = class(TCalcThread)
private
protected
procedure Execute; override;
end;

T2nd = class(TCalcThread)
private
protected
procedure Execute; override;
end;

var Form1:TForm1;

implementation

{$R *.dfm}

constructor TCalcThread.Create(A:TStrAr);
begin
inherited Create(False);
FA:=A; FIsDone:=False end;

procedure T1st.Execute;
var i:integer;
begin for i:=1 to 10 do FB[i]:=FA[i]+1; FIsDone:=True end;

procedure T2nd.Execute;
var i:integer;
begin for i:=1 to 10 do FB[i]:=sqr(FA[i]); FIsDone:=True end;

procedure TForm1.Button1Click(Sender:TObject);
var t1,t2:TCalcThread; m:TStrAr; i:integer;
begin
for i:=1 to 10 do m[i]:=2*i;
t1:=T1st.Create(m); t2:=T2nd.Create(m);
While True Do Begin
If t1.IsDone And t2.IsDone Then Begin
for i:=1 to 10 do begin
Memo1.Lines.Add(inttostr(t1.B[i])); Memo1.Lines.Add(inttostr(t2.B[i])) end;
FreeAndNil(t1); FreeAndNil(t2) End; Sleep(200) End
end;

end.


После компиляции выскакивает access violation. Почему это происходит? Помогите найти ошибку в коде. Спасибо


Valdis   (2013-07-18 12:06:00) [1]

Всем спасибо, разобрался


icWasya   (2013-07-18 09:24:00) [2]

Valdis, внимательно смотри, о чём тебя Cobalt  спрашивает в
(17.07.13 22:28) [11]
(17.07.13 23:16) [13]

constructor TCalcThread.Create(A:TStrAr);
begin
inherited Create(False); /// <<===--- вот здесь ты вызываешь Thread.Create


Читай справку, что означает этот параметр


MBo   (2013-07-18 06:00:00) [3]


While True Do Begin
  If t1.IsDone And t2.IsDone Then Begin
      for i:=1 to 10 do begin
          Memo1.Lines.Add(inttostr(t1.B[i]));
          Memo1.Lines.Add(inttostr(t2.B[i]))
     end;
     FreeAndNil(t1);
     FreeAndNil(t2);
     Break;
  End;
  Sleep(200);
End


Valdis   (2013-07-17 23:55:00) [4]

@ Cobalt

Аргументов всего три. Один массив исходных данных, второй это преобразованный массив (a -> b), который выдают потоки, и третий это логическая переменная которая говорит о завершении потока. Если что-то неверно покажите на коде, ато я так не догоняю. Если мне все было понятно, то я не спросил бы.

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


Cobalt   (2013-07-17 23:16:00) [5]

Рекомендую обратить внимание на конструктор именнокласса TThread, коий ты вызываешь с некоторым аргументом.


Valdis   (2013-07-17 22:56:00) [6]

@ Cobalt
в конструкторе создания TCalcThread параметр - массив, который будет браться из главной программы. А что там еще должно быть?


Cobalt   (2013-07-17 22:28:00) [7]

Valdis
А теперь посмотри, что за параметр в конструкторе создания TThread


Valdis   (2013-07-17 22:11:00) [8]

@ sniknik В начале создаем (create), а потом выполняем (execute) разве не такая логика? Я читал что inherited create нужен в constructor, а не в execute. Или вы имеете в виду что нужно удалить (False) и просто оставить inherited Create?

Папка демо пустая наверно надо переустановить. Примеров много, но толковые найти нелегко.

@ Anatoly Podgoretsky А что здесь синхронизировать? Потоки независимы друг от друга и не перекрываются.


Anatoly Podgoretsky   (2013-07-17 21:43:00) [9]

Надо использовать синхронизацию (synhronize)


sniknik   (2013-07-17 21:39:00) [10]

> И ещё насчёт сообщения от RWolf про inherit?
он имеет в виду что "рабочая процедура" - execute начинает выполнятся после создания (если не параметр "приостановлено"), а у тебя вызов родительского create до того как инициализировал параметры используемые в execute...
хотя... так ли это важно если сам create у тебя виртуальный? есть ли у него "родитель"? :)

p.s.  в дельфе есть хороший пример на потоки... папка Demos\Threads.


MBo   (2013-07-17 20:45:00) [11]

>У меня с тредами проблемы
Эта проблема не с тредами, а с логикой цикла. Как поправить - я подсказал


Valdis   (2013-07-17 20:38:00) [12]

Уважаемый MBo подскажите (на коде) как правильно. У меня с тредами проблемы. И ещё насчёт сообщения от RWolf про inherit?


MBo   (2013-07-17 20:34:00) [13]

цикл надо прервать- break или проверку условия добавить


Valdis   (2013-07-17 20:09:00) [14]

А как правильно уничтожить потоки. Как это исправить?


MBo   (2013-07-17 19:50:00) [15]

в цикле While True уничтожаются потоки, но он продолжается.
Это можно было заметить при отладке.


Valdis   (2013-07-17 19:30:00) [16]

А как правильно? Я поставил его в конец и все равно access violation


RWolf   (2013-07-17 19:24:00) [17]

inherited Create(False); //запустил поток прежде, чем запомнил аргументы.


Наверх

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