![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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); //запустил поток прежде, чем запомнил аргументы.