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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 28.09.2020, 09:59   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию Синхронизация потока по событию извне потока

Здравствуйте.
Есть массив TFrame, в каждом из которых есть поток, качающий файл из интернета.
Код максимально урезан, дабы показать суть.
Код:
type
  TFrameDownload = class;

  TThreadDownload = class(TThread)
    public
      DnlObj : TWinApiDownload;
      frame : TFrameDownload;
    private
      currentFilesize : Int64;
      currentlyTransfered : Int64;
      procedure DownloadStart(Sender : TObject; iFileSize : Int64);
      procedure DownloadWork(Sender : TObject; transfered : Int64);
      procedure DownloadEnd(Sender : TObject; iFileSize : Int64; ErrorCode : Integer);
      procedure Synchronize_Start;
      procedure Synchronize_Work;
	protected
      procedure Execute; override;
  end;

procedure TThreadDownload.Execute;
var
  mem : TMemoryStream;
begin
  DnlObj := TWinApiDownload.Create;
  DnlObj.OnWorkStart := DownloadStart;
  DnlObj.OnWork := DownloadWork;
  DnlObj.OnWorkEnd := DownloadEnd;

  DnlObj.URL := 'https://d3c27h4odz752x.cloudfront.net/1e4ecdd1f104f7d155b7_miramisu_627579506_1503292578/chunked/30.ts';

  while not Terminated do
  begin
    mem := TMemoryStream.Create;
    DnlObj.Download(mem);
	mem.Free;
  end;
  DnlObj.Free;
end;

procedure TThreadDownload.DownloadStart(Sender: TObject; iFileSize: Int64);
begin
  currentFilesize := iFileSize;
  Synchronize(Synchronize_Start);
end;

procedure TThreadDownload.DownloadWork(Sender: TObject; transfered: Int64);
begin
  currentlyTransfered := transfered;
  Synchronize(Synchronize_Work);
end;

procedure TThreadDownload.DownloadEnd(Sender: TObject; iFileSize: Int64; ErrorCode: Integer);
begin
  //
end;

procedure TThreadDownload.Synchronize_Start;
begin
  frame.ProgressBar1.Max := currentFilesize;
end;

procedure TThreadDownload.Synchronize_Work;
begin
  frame.ProgressBar1.Position := currentlyTransfered;
end;

procedure TFrameDownload.Event_DownloadTerminate(Sender : TObject);
begin
  fThreadDownload := nil;
  btnStart.Enabled := True;
end;

//запуск потока
procedure TFrameDownload.btnStartClick(Sender: TObject);
begin
  if fThreadDownload = nil then
  begin
    btnStart.Enabled := False;
    fThreadDownload := TThreadDownload.Create(True);
    fThreadDownload.FreeOnTerminate := True;
    fThreadDownload.OnTerminate := Event_DownloadTerminate;
    fThreadDownload.frame := Self;

    fThreadDownload.Resume;
  end;
end;

//остановка потока
procedure TFrameDownload.btnStopClick(Sender: TObject);
begin
  if fThreadDownload <> nil then
  fThreadDownload.Terminate;
end;
Этот поток синхронизируется с фреймом каждый раз, когда скачано некоторое количество информации (например 4кб). Это условие прописано в классе TWinApiDownload. Но меня такой подход не устраивает. Хотелось бы синхронизироваться по событию. Например - по кнопке или таймеру. Нажали кнопку и на форму (фрейм) вывелась информация из потока. Как это сделать? Ведь нельзя же обращаться к работающему потоку. Тогда файл скачается не правильно. Я уже пробовал. У него тогда хэш с оригиналом не сходится. Чуть с ума не сошел, пока не допёр, из-за чего это происходит.
BLACK_RAIN вне форума Ответить с цитированием
Старый 28.09.2020, 11:49   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Ведь нельзя же обращаться к работающему потоку.
Читать данные можно. Главное что-бы объект существовал. Поэтому удаление объектов должен делать главный объект, а не поток сам.

Код:
while not Terminated do
 ...
fThreadDownload.FreeOnTerminate := True;
А ничего что у вас скачивание по кругу идет?

Вот пример с таймером.
Вложения
Тип файла: rar Демонстрация работы потоков с таймером.rar (164.4 Кб, 3 просмотров)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 28.09.2020, 12:58   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Pavia Посмотреть сообщение
Читать данные можно. Главное что-бы объект существовал.
Я так уже пробовал. У скачанного файла хэш не сходится с оригиналом.
Цитата:
Сообщение от Pavia Посмотреть сообщение
Поэтому удаление объектов должен делать главный объект, а не поток сам.
У меня так и есть. Но я не понял, при чём тут это вообще? У меня же вопрос про другое.
Цитата:
Сообщение от Pavia Посмотреть сообщение
Вот пример с таймером.
Я качал конкретные файлы из интернета.
А вы в потоках работаете со случайными числами. Как вы узнали, что хэш сошелся? С чем вы сравнивали?
Цитата:
Сообщение от Pavia Посмотреть сообщение
А ничего что у вас скачивание по кругу идет?
Да ничего
Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Код максимально урезан, дабы показать суть.
BLACK_RAIN вне форума Ответить с цитированием
Старый 28.09.2020, 13:24   #4
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Код максимально урезан, дабы показать суть.
Так то код должен быть не просто минимальным, но и рабочий. А у Вас больше чем пол проекта надо дописать прежде чем он заработает.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 28.09.2020, 14:15   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Pavia Посмотреть сообщение
Так то код должен быть не просто минимальным, но и рабочий
С чего вы решили, что этот код не рабочий?
Цитата:
Сообщение от Pavia Посмотреть сообщение
А у Вас больше чем пол проекта надо дописать прежде чем он заработает.
что вы понимаете под "заработает"?
У меня уже есть работающий проект. Но при чём тут это?
Я же вам объяснил, в чем проблема и привёл минимальный кусок кода, где возникает ошибка. Так все делают. Что вас не устраивает? Что-то изменилось? Теперь надо выкладывать весь проект, а не только кусок кода с ошибкой? Если так, то я выложу.

Последний раз редактировалось BLACK_RAIN; 28.09.2020 в 14:56.
BLACK_RAIN вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Синхронизация одного потока zumm Свободное общение 26 01.10.2013 10:10
Как получить доступ к методу потока(TThread) из основного потока? Pcrepair Общие вопросы Delphi 3 30.03.2013 14:52
Должно быть 3 потока. А диспетчер задач показывает, что потока создано 2 BEL9ILLI Общие вопросы Delphi 3 06.12.2011 20:26
Как узнать номер потока из самого потока? GaMeSTeR Помощь студентам 0 03.12.2010 09:50
Два потока tigrend Общие вопросы .NET 6 24.04.2010 08:25