Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.03.2019, 22:44   #1
Владимир_Юрьевич
Новичок
Джуниор
 
Регистрация: 08.03.2019
Сообщений: 2
Вопрос Нужна помощь в ознакомлении с многопотоковыми приложениями на Delpi 7

Приветствую! Начал ознакамливаться с потоками на делфи для себя и возможной дипломной работы. В теории всё понятно, а на практике возникают проблемы, программа не хочет выполнять больше 1 потока по нажатию кнопки. Задачка простая - создать массив из N элементов, его перемешивание и поиск чисел с одинаковыми цифрами. По нажатию на кнопку для каждого потока, каждый из потоков выполняется нормально, ошибок нет, работает каждый раз, каждый запуск (проверял с 2-мя потоками). объединяю их в параллельную работу по нажатию кнопки, не хочет, ошибки и всё. Скину код и скриншоты примерных ошибок, буду рад быстрому ответу))
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Label1: TLabel;
    Edit1: TEdit;
    BitBtn2: TBitBtn;
    BitBtn3: TBitBtn;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMassiveThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

  TUppMassiveThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

  type
  TNumThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  Massive:TMassiveThread;
  UpdateMassive: TUppMassiveThread;
  Numerals: TNumThread;
  n:integer;

implementation

uses Unit2, Unit3, Unit4;

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.Terminate;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Massive:=TMassiveThread.Create(False);
Massive.Priority:=tpNormal;
UpdateMassive:=TUppMassiveThread.Create(False);
UpdateMassive.Priority:=tpNormal;
Numerals:=TNumThread.Create(False);
Numerals.Priority:=tpNormal;
Form2.Show;
Form3.Show;
Form4.Show;
end;

procedure TMassiveThread.Execute;
var i:integer;
begin
  n:=StrToInt(Form1.Edit1.Text);
  Form2.Memo1.Lines.Clear;
  for i:=0 to n-1 do
  Form2.Memo1.Lines.Add(IntToStr(random(1999)-999));
end;

procedure TUppMassiveThread.Execute;
var i,j,k:integer;
    a:string;
begin
  Randomize;
  Form3.Memo1.Lines.Clear;
  for i:=0 to n-1 do Form3.Memo1.Lines.Add(Form2.Memo1.Lines[i]);
  for i:=0 to Form3.Memo1.Lines.Count-1 do
  begin
    repeat
      j:= Random(Form3.Memo1.Lines.Count);
    until (j <> i);
    a:=Form3.Memo1.Lines[i];
    Form3.Memo1.Lines[i]:=Form3.Memo1.Lines[j];
    Form3.Memo1.Lines[j]:=a;
  end;
end;

procedure TNumThread.Execute;
begin

end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
{
Form2.Show;
Form3.Show;
Form4.Show;}
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
begin
{
Form2.Show;
Form3.Show;
Form4.Show; }
end;

end.
1.jpg

2.jpg
серого окна быть не должно, должно быть перемешанные значения.
3.jpg
Владимир_Юрьевич вне форума Ответить с цитированием
Старый 09.03.2019, 00:24   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Владимир_Юрьевич
Переписать весь код.

Визуальные компоненты не являются потоко-безопасными. Это значит, вы должны сами их обезопасить. Отсюда ваши ошибки. Многим не очевидно, но факт в том, что форма и мемо являются для потоков общими ресурсами. А теория гласит, что доступ к общим ресурсам должен быть обезопасен путём использования примитивов синхронизации.

Мьютексы, критические секции и тому подобное.
Ещё можно раздать каждому потоку свой диапазон в массиве. Но только в масиве, а не в Memo.

Я так понял вы хотите менять размер массива, то вы должны послать сообщения потокам с требованиям остановится на перекур. Дождаться пока все второстепенные потоки остановятся и только тогда из основного потока вы сможете изменить размер массива, а после вновь запустить остановленные потоки одновременно просигнализировав им о изменении размера массива. Вернее вначале по сигнализировать потом запустить.


Причем просто так усыпить поток не получится, его нужно перевести в безопасное состояние в котором он готов к изменению его же переменных.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 09.03.2019 в 00:30.
Pavia вне форума Ответить с цитированием
Старый 09.03.2019, 06:58   #3
Владимир_Юрьевич
Новичок
Джуниор
 
Регистрация: 08.03.2019
Сообщений: 2
Радость Вроде пошло

Спасибо за помощь, вроде пашет! ошибок нет. Только при дальней повторной работе (запуске) с 5-10 раза. Для знаний пойдет. Если есть какие то ошибки, укажите, чтоб закрепить знания)

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2, Unit3, Unit4, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Label1: TLabel;
    Edit1: TEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BitBtn1Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMassiveThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

  TUppMassiveThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

  TNumThread = class(TThread)
  private
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  Massive:TMassiveThread;
  UpdateMassive: TUppMassiveThread;
  Numerals: TNumThread;
  n,i,j,a,b,c,z,l:integer;
  t:string;
  m1:array of string;
  m2:array of string;
  m3:array of string;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.Terminate;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
SetLength(m1,n);
SetLength(m2,n);
SetLength(m3,n);
Massive:=TMassiveThread.Create(False);
Massive.Priority:=tpTimeCritical;
Form2.Memo1.Lines.Clear;
l:=High(m1);
sleep(10);
for i:=0 to l do
Form2.Memo1.Lines.add(m1[i]);
UpdateMassive:=TUppMassiveThread.Create(False);
UpdateMassive.Priority:=tpIdle;
l:=High(m2);
Form3.Memo1.Lines.Clear;
sleep(10);
for i:=0 to l do
Form3.Memo1.Lines.add(m2[i]);
Numerals:=TNumThread.Create(False);
Numerals.Priority:=tpIdle;
Form4.Memo1.Lines.Clear;
sleep(10);
l:=High(m3);
for i:=0 to l do
begin
if m3[i]<>'' then Form4.Memo1.Lines.add(m3[i]);
end;
SetLength(m1,0);
SetLength(m2,0);
SetLength(m3,0);
Form2.Show;
Form3.Show;
Form4.Show;
end;

procedure TMassiveThread.Execute;
begin
  for i:=0 to n-1 do
  m1[i]:=IntToStr(random(1999)-999);
end;

procedure TUppMassiveThread.Execute;
begin
  Randomize;
  for i:=0 to n-1 do m2[i]:=m1[i];
  for i:=0 to n-1 do
  begin
    repeat
      j:= Random(n);
    until (j <> i);
    t:=m2[i];
    m2[i]:=m2[j];
    m2[j]:=t;
  end;
end;

procedure TNumThread.Execute;
begin
for i:=0 to n-1 do
begin
z:=StrToInt(m1[i]);
if z>10 then begin
a:=z div 100;
b:=z div 10 mod 10;
c:=z mod 10;
if (a=b)and(a=c)and(c=b)then
m3[i]:=IntToStr(z);
end;
end;
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
if Form1.Edit1.Text<>'' then
begin
Form1.BitBtn1.Enabled:=True;
n:=StrToInt(Form1.Edit1.Text);
end
else
Form1.BitBtn1.Enabled:=False;
end;

end.
Владимир_Юрьевич вне форума Ответить с цитированием
Старый 09.03.2019, 08:07   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Код:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
SetLength(m1,n);
SetLength(m2,n);
SetLength(m3,n);
Massive:=TMassiveThread.Create(False);//итак запустили параллельный процесс 
Massive.Priority:=tpTimeCritical;
Form2.Memo1.Lines.Clear;
l:=High(m1);
sleep(10); // я так понимаю "пытаемся" чего-то дождаться от запущенного выше процесса
for i:=0 to l do  // и "дождавшись" что-то собираемся делать
Form2.Memo1.Lines.add(m1[i]);
Код:
sleep(10); // я так понимаю "пытаемся" чего-то дождаться от запущенного выше 
а если нельзя sleep то не нужно ЗДЕСЬ и все последующее.
прежде всего "реальный" (для практических целей) процесс за такое время время не выполнит своей задачи.
а ожидание действительно значимой величины времени "повесит" основной поток на то самое время за которое он и сам смог бы выполнить это.
второе. никто не может гарантировать что действие будет выполнено за отведенное время.
для извещения основного(или любого другого) об ОКОНЧАНИИ действий потока есть OnTeminate

Код:
Massive:=TMassiveThread.Create(False);//итак запустили параллельный процесс 
Massive.OnTerminate:=self.AfterStopMassive; // по окончании запустить ЭТУ процедуруЭТОТ метод формы в ОСНОВНОМ потоке
Код:
procedure TForm1.AfterStopMasive(sender: TObject);
begin
  mas:=sender as TMassive;
  ... // мы знаем что поток mas уже ВЫПОЛНИЛ заданное действие и можем ...
end;
http://www.programmersforum.ru/showthread.php?t=295305
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 09.03.2019 в 08:13.
evg_m на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Delpi and winapi Кольша Win Api 5 29.01.2012 23:02
Delpi-перекодировка Бурундук Помощь студентам 9 21.08.2010 13:27
Классы в delpi Koby Помощь студентам 6 15.06.2010 21:39
Очень нужна помощь c матрицами, макросами в Excel. Заранее благодарен(поверьте, очень-очень нужна помощь) Farridjan Помощь студентам 1 03.07.2009 12:24
Очень нужна помощь с написанием программы... срочно(буду благодарен за помощь) 5Paladin5 Помощь студентам 3 02.07.2009 09:12