Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Упростить работу с потоком


Автор: valerchi 1.3.2011, 01:02
Помогите упростить работу с потоком. Вот в чём суть : запускается программа и сразу запускается второй поток, который считает бесконечный цикл и записывает значение цикла в файл. Потом по нажатию кнопки на форме открывается этот файл, в который записано значение, значение считывается и выводится на экран. Можно ли сделать так, чтобы никаких файлов не было, а значение бралось при нажатии кнопки непосредственно из второго , работающего потока и выводилось на экран? Вот что у меня имеется:
Код

unit potokslch;

interface

uses
  Classes;

type
  potok = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    
  end;

implementation

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure potok.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ potok }

procedure potok.Execute;
var f:textfile;x:integer; label l;
begin
  { Place thread code here }
begin
x:=0;
repeat

x:=x+1;
if x=53 then x:=1;
l: begin
assignfile(f,'d:\два потока.txt');
{$i-}
rewrite(f);
{$I+}
if IOResult <> 0 then   goto l;
writeln(f,(x));
closefile(f);
end;
until (x=68);
end;
end;

end.
 


И главный поток:
Код

unit Sluchainie_chisla_dva_potoka;

interface

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

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

var
  Form1: TForm1;
  x:string; Fpotok: potok;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
f: TextFile; // файл
label l;
begin
Fpotok := potok.Create(False);
l:
AssignFile(f, 'd:\два потока.txt');
{$i-}
Reset(f); // открыть для чтения
{$I+}
if IOResult <> 0 then    goto l;
begin
readln(f, x); // прочитать строку из файла
CloseFile(f); // закрыть файл
end;
end;
memo1.lines.Add(x);


end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin

   Fpotok.Terminate;
   Fpotok.Free;

end;

end.

Автор: kami 1.3.2011, 01:23
Код

procedure potok.Execute;
  ...
  ReturnValue:=x;
  .....
end;

...
memo1.lines.Add(IntToStr(FPotok.ReturnValue));


Посмотрите внимательно на метод Button1Click.
Что будет, если нажать на кнопку 2 раза? Правильно, будет создан второй поток, а о созданном при первом нажатии программа просто забудет, а Windows будет помнить. И начнут эти 2 потока бороться за несчастный файл...
Как минимум, там нужно
Код

  if not Assigned(FPotok) then
    FPotok:=potok.Create;


В остальное страшно вникать.

Автор: northener 1.3.2011, 02:45
Цитата(valerchi @  1.3.2011,  01:02 Найти цитируемый пост)
Помогите упростить работу с потоком. Вот в чём суть : запускается программа и сразу запускается второй поток, который считает бесконечный цикл и записывает значение цикла в файл. Потом по нажатию кнопки на форме открывается этот файл, в который записано значение, значение считывается и выводится на экран. Можно ли сделать так, чтобы никаких файлов не было, а значение бралось при нажатии кнопки непосредственно из второго , работающего потока и выводилось на экран?


Можно.
Но лучше сразу сформулировать задачу, а не вопрос.

Автор: valerchi 1.3.2011, 12:11
Сделал так, - второй поток запускается, когда активируется форма. Но опять ничего не получается. Вот что получилось:
Код

unit Sluchainie_chisla_dva_potoka;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,potokslch, StdCtrls, Buttons;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    BitBtn1: TBitBtn;
    procedure Button1Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  x:string; Fpotok: potok;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin

memo1.lines.Add(x);

end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
   Fpotok.Terminate;
   Fpotok.Free;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
Fpotok := potok.Create(False);
end;

end.

И второй поток:
Код

unit potokslch;

interface

uses
  Classes;

type
  potok = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    
  end;

implementation

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure potok.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ potok }

procedure potok.Execute;
var x:integer; label l;
begin
  { Place thread code here }
begin
x:=0;
repeat

x:=x+1;
if x=53 then x:=1;
until (x=68);
end;
end;
end.


Автор: cat512 1.3.2011, 13:01
Самый простой вариант:
Сделай свойство у второго потока, которое будет иниц. в цикле, а в главном потоке считывай это свойство.

Автор: valerchi 1.3.2011, 22:46
Цитата(cat512 @ 1.3.2011,  13:01)
Самый простой вариант:
Сделай свойство у второго потока, которое будет иниц. в цикле, а в главном потоке считывай это свойство.

А как конкретно это сделать?

Автор: valerchi 2.3.2011, 13:01
Цитата(kami @ 1.3.2011,  01:23)
Код

procedure potok.Execute;
  ...
  ReturnValue:=x;
  .....
end;

...
memo1.lines.Add(IntToStr(FPotok.ReturnValue));



Сделал так, а мне высвечивает :  Undeclared identifier: 'ReturnValue'

Автор: valerchi 3.3.2011, 12:51
Неужели ничего нельзя сделать? Как я понимаю, теоретически это должно было выглядеть так: второй поток выполняет бесконечный цикл и заносит значен6ие  "х" в какой - нибудь буфер памяти, а главный поток при нажатии кнопки считывает эту информацию и выдаёт на экран. В моём случае вместо буфера памяти у меня создавался файл, записывался туда результат, а главный поток его считывал. Но это слишком громоздко и неудобно. Может кто знает, как создать такой буфер памяти?

Автор: MetalFan 3.3.2011, 13:47
valerchi, а что мешает перейти от теории к практике?
Не знаете, как выделить буфер в памяти? или что использовать в качестве буфера? как обеспечить "раздельный" доступ к буферу?
Просто вопрос выглядит как "я ничего не знаю, подскажите, что делать".
Перво наперво рекомендую к обязательному прочтению статью http://forum.vingrad.ru/forum/topic-60076.html. Если что-то непонятно после первого прочтения, прочитать еще раз.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)