powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Потоки. Возврат значения функции.
19 сообщений из 19, страница 1 из 1
Потоки. Возврат значения функции.
    #39725500
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Друзья, нужен совет специалиста по потокам. Я объявляю свой класс TMyFile, который включает в себя 2 строковые переменные - имя файла и его хэш. Описан вызов рассчёта хэша, выведенный в поток. Передаю стринговое поле Hash в поток, рассчёт нормальный, но в поле ничего не прилетает.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
type
  TMyThread = class(TThread)
    FHash: ^string;
    FName: string;
    constructor Create(CreateSuspended: Boolean; Filename:string; var Hash: string);
    procedure Execute; override;
    procedure Update;
end;

type
  TMyFile = class(TObject)
  public
    OriginalName: string;
    Hash: string;
    constructor Create;
    destructor Destroy; override;
    function CalculateHash:string;
end;

implementation

constructor TMyThread.Create(CreateSuspended: Boolean; Filename:string; var Hash: string);
begin
  FName:=Filename;
  FHash:=@Hash;
  inherited Create(CreateSuspended);
end;

procedure TMyThread.Execute;
begin
 while not Terminated do
 begin
    FHash^:=MD5DigestToStr(MD5File(FName));
    Terminate;
 end;
 Synchronize(Update);
end;

procedure TMyThread.Update;
begin
  //Showmessage(FHash^);  // РАссчитанный хэш выводится нормально
end;
//===================================================
function TMyFile.CalculateHash:string;
var DT: TMyThread;
begin
  //if FileExists(OriginalName) then result:=MD5DigestToStr(MD5File(OriginalName)) else result:='';   //Выполнение этой операции выношу в отдельный поток
  DT := TMyThread.Create(true,OriginalName,Hash);
  DT.FreeOnTerminate:= True;
  DT.Execute;
end;
//=================[Из другого юнита]==================================
procedure TForm1.N1Click(Sender: TObject);
var DF: TMyFile;
begin
  if OpenFile.Execute then
  begin
    DF:=TMyFile.Create;
    DF.OriginalName:=ExtractFilename(OpenFile.FileName);
    DF.Hash:=DF.CalculateHash;
    while df.Hash='' do begin end;     /////Этот цикл не прекращается
    showmessage(df.Hash);
    DF.Destroy;
  end;
end;

...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725506
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Небольшое исправление
Было:
Код: pascal
1.
DF.OriginalName:=ExtractFilename(OpenFile.FileName);


Стало:
Код: pascal
1.
DF.OriginalName:=OpenFile.FileName;


Проблема осталась
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725533
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus, и где результат функции function TMyFile.CalculateHash? Результата нет, поэтому нет и DF.Hash
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725537
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
goldmi45, бесконечным циклом я жду пока поток заполнит переданные поле вычисленным значением. Значение поток вычисляет, но память, отведенную под поле Hash не заполняет.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725587
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus,

ну заведите в потоке переменную типа TMyFile и присвойте ей значение экземпляра
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
type
  TMyFile = class;
  TMyThread = class(TThread)
    FHash: ^string;
    FName: string;
    FFile: TMyFile;
    constructor Create(CreateSuspended: Boolean; Filename:string; aFile: TMyFile; var Hash: string);
    procedure Update;
    ....
end;

procedure TMyThread.Update;
begin
  FFile.Hash := FHash^;
end;

procedure TMyFile.CalculateHash:string;
var DT: TMyThread;
begin
  DT := TMyThread.Create(true,OriginalName, Self, Hash);
  DT.FreeOnTerminate:= True;
  DT.Execute;
end;
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725594
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus,

Передавать адрес строки - не самая хорошая идея.
Добавь в объект поток обработчик OnTerminate, в нём и заполняй значение.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725614
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus,

а так?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
  TMyThread = class(TThread)
    FHash: string;
  <skiped>
  end;

constructor TMyThread.Create(CreateSuspended: Boolean; Filename:string; var Hash: string);
begin
  inherited Create(CreateSuspended);
  FName:=Filename;
  FHash:=Hash;
  FreeOnTerminate:= True;

  if Suspended then Resume;
end;

procedure TMyThread.Execute;
begin
 while not Terminated do //вот это вообще сомнительная конструкция, 
                         //поскольку FName задается только один раз при создании потока
   FHash:=MD5DigestToStr(MD5File(FName));
 Synchronize(Update);
end;

procedure TMyThread.Update;
begin
  TMyFile.Hash:=FHash;  
end;
//===================================================
function TMyFile.CalculateHash:string;
var DT: TMyThread;
begin
  DT:= TMyThread.Create(true,OriginalName,Hash);
end;

...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725633
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пересмотрел логику. Решил, что из формы берётся только имя файла и передаётся потоку строка. Этот поток сам создаёт TMyFile, считает хэш и в качестве отладки выводит на экран. Вопрос, а почему я стартую поток, а главная форма не отвисает и чего-то ждёт?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
//===================================================================
// ЮНИТ формы. Здесь просто беру файл и путь передаю потоку.
type
  TMyThread = class(TThread)
    FName: string;
    //FHash: string;     //для отладки
    constructor Create(CreateSuspended: Boolean; Filename:string);
    procedure Execute; override;
    procedure Update;
end;

procedure TForm1.N1Click(Sender: TObject);
var DT: TMyThread;
begin
  if OpenFile.Execute then
  begin
    DT:=TMyThread.Create(true,OpenFile.FileName);
    DT.FreeOnTerminate:=true;
    DT.Execute;
  end;
end;
//==============================================================================
constructor TMyThread.Create(CreateSuspended: Boolean; Filename:string);
begin
  FName:=Filename;
  inherited Create(CreateSuspended);
end;

procedure TMyThread.Execute;
var DF: TMyFile;
begin
  DF:= TMyFile.Create;
  while not Terminated do
  begin
    DF.OriginalName:=FName;
    DF.Hash:=DF.CalculateHash;
    //FHash:=DF.Hash; // для отладки выдёргиваю значение для Update
    Synchronize(Update);
    Terminate;
  end;
  DF.Destroy;
end;

procedure TMyThread.Update;
begin
  //Showmessage(FHash); для отладки проверяю - Значение приходит
end;
//=================[Из другого юнита]==================================
type
  TMyFile = class(TObject)
  public
    OriginalName: string;
    Hash: string;
    constructor Create;
    destructor Destroy; override;
    function CalculateHash:string;
end;

function TMyFile.CalculateHash:string;
begin
  if FileExists(OriginalName) then result:=MD5DigestToStr(MD5File(OriginalName)) else result:=''; 
end;

...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725677
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rusВопрос, а почему я стартую поток, а главная форма не отвисает и чего-то ждёт?Потому, что ты создаешь поток спящим и не будишь, а выполняешь его код в основном потоке.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725682
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock, спасибо! Заработался :)
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725683
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus,

Совет. Если ты собираешься в основном потоке тупо ждать результата работы доп. потока - это означает, что доп. поток абсолютно не нужен.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725690
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock, ну это ясен красен :) Исправил. Я потоку скармливаю путь. Он потом будет хэш считать, в сокет стримить. Ну и форме посылать сообщения о своей активности. Пока всё по плану.
Большое всем спасибо за участие!
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725694
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function TMyFile.CalculateHash:string;
var DT: TMyThread;
begin
  //if FileExists(OriginalName) then result:=MD5DigestToStr(MD5File(OriginalName)) else result:='';   //Выполнение этой операции выношу в отдельный поток
  DT := TMyThread.Create(true,OriginalName,Hash);
  DT.FreeOnTerminate:= True;
  DT.Execute;
end;
......
DF.Hash:=DF.CalculateHash;

Уникальнейший код.

1. Поток создается спящим
2. Прямой вызов метода Execute
3. Функция, которая ничего не возвращает
4. Перезаписывание поля мусором, возвращенным из метода
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725701
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_, логика пересмотрена см. 21720004 . Был не прав, повзрослел
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725817
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rusлогика пересмотрена см.Лучше.

1. Цикл while not Terminated и явный вызов Terminate нафиг не нужен
2. Нужно ли поле с хешем экземпляру класса TMyFile? Если да, сделать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  TMyFile = class(TObject)
  private
    FHash: string;
  public
    OriginalName: string;
    property Hash: string read FHash;
    constructor Create;
    destructor Destroy; override;
    procedure CalculateHash: string;
  end;

procedure TMyFile.CalculateHash;
begin
  if FileExists(OriginalName) then FHash:=MD5DigestToStr(MD5File(OriginalName)) else FHash:=''; 
end;

если нет - сделать так
OxY63rus
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
procedure TMyThread.Execute;
var
  DF: TMyFile;
  Hash: string;
begin
  DF:= TMyFile.Create;
  while not Terminated do
  begin
    DF.OriginalName:=FName;
    Hash:=DF.CalculateHash;
    //FHash:=DF.Hash; // для отладки выдёргиваю значение для Update
    Synchronize(Update);
    Terminate;
  end;
  DF.Destroy;
end;


3.
OxY63rus
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
procedure TForm1.N1Click(Sender: TObject);
var DT: TMyThread;
begin
  if OpenFile.Execute then
  begin
    DT:=TMyThread.Create(true,OpenFile.FileName);
    DT.FreeOnTerminate:=true;
    DT.Execute;
  end;
end;

_Vasilisk_1. Поток создается спящим
2. Прямой вызов метода Execute
3. Смысла существования класса TMyFile я не вижу
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725818
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OxY63rus
По сути тебе не нужны никакие классы, надо просто параллельно запустить лишь одну функцию.
что-то вроде:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
TThread.CreateAnonymousThread(
    procedure
    var AHash: string;
    begin
      AHash:=MD5DigestToStr(MD5File(FileName));
      TThread.Synchronize(procedure 
      begin
         Showmessage(AHash);
      end);
    end).Start;


Ну а ждать потоки из главного потока дело кривое - забей.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725833
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimonkaНу а ждать потоки из главного потока дело кривое - забей.
Ну почему же. Если поток не Anonymous (и соотв. не FreeOnTerminate) - то вполне работоспособная вещь. Запустил операцию - задизейблил все контролы кроме кнопок Стоп и Закрыть. И варианты:
a) Закончилась операция (пришло сообщение по PostMessage) - раздизейблил, обработал результаты, Tread.Free, убрал Стоп.
б) Нажали Стоп - раздизейблил, Tread.Free, убрал Стоп;
в) Нажали Закрыть - Tread.Free, Close.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725843
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockDimonkaНу а ждать потоки из главного потока дело кривое - забей.Ну почему же. Если поток не Anonymous (и соотв. не FreeOnTerminate) - то вполне работоспособная вещь. Запустил операцию - задизейблил все контролы кроме кнопок Стоп и Закрыть. И варианты:
a) Закончилась операция (пришло сообщение по PostMessage) - раздизейблил, обработал результаты, Tread.Free, убрал Стоп.
б) Нажали Стоп - раздизейблил, Tread.Free, убрал Стоп;
в) Нажали Закрыть - Tread.Free, Close. И да и нет. Ты описал случай когда ждёт пользователь, а не функция. Это разные вещи.
...
Рейтинг: 0 / 0
Потоки. Возврат значения функции.
    #39725880
OxY63rus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_3. Смысла существования класса TMyFile я не вижу
Конечно всё не просто так, прежде чем сюда задать вопрос пришлось очень много выкинуть чего и оставить только то, что касается вопроса. Для экономии Вашего же времени.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Потоки. Возврат значения функции.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]