Сообщений: 5,863
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
Собственно прошу помощи. Не могу понять в чем примерно дело. Все работает, только вот программа на сохранении виснет. Решил запилить сохранение в поток, дабы не подвисала. В итоге основной поток ждет, пока завершится другой. Если у кого-то есть пример сохранения стрима в потоке - просьба выложить.
Сообщений: 343
Тем: 4
Зарегистрирован: Jan 2011
Репутация:
2,824
Лучше кинуть кусок кода, какой поправить, по описанию ниче не понятно, что где зависает.
Сообщений: 5,863
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
Код: unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP, StdCtrls, ShellAPI, inifiles, ExtCtrls,
IdAntiFreezeBase, IdAntiFreeze, Math;
type
TSaveFile = class(TThread)
public
stream:TMemoryStream;
path:string;
procedure Execute;override;
constructor Create(stream:TMemoryStream; path:string);
end;
TForm1 = class(TForm)
StatusBar1: TStatusBar;
IdHTTP1: TIdHTTP;
{ Class declarations }
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ver,
paths,
filed:string;
implementation
{$R *.dfm}
procedure TSaveFile.Execute;
begin
Stream.SaveToFile(path); //сохраняем данные из потока на жестком диске
end;
//Вызов конструктора родительского класса
constructor TSaveFile.Create(Stream:TMemoryStream; path:string);
begin
inherited Create(True); //Поток создаем в состоянии «Приостановлен»
Stream:=Stream; //Инициализация параметров
path:=path;
FreeOnTerminate:=True; //Поток освободит ресурсы при окончании работы
Self.Priority:=tpHighest; //Стартуем с высоким приоритетом
Resume; //Переводим поток в состояние «Активен»
end;
procedure TForm1.Download(obj,path:string);
var Stream:TMemoryStream;
SaveFile:TSaveFile;
begin
Stream:=TMemoryStream.Create; //выделение памяти под переменную
try
//obj:='http://files-w2.asterios.tm:88/high_five_asterios.7z';
idHTTP1.Get(obj, Stream); //загрузка в поток данных из сети
SaveFile:=TSaveFile.Create(stream,path);
Application.ProcessMessages;
except
//
end;
Stream.Free; //освобождаем память
end;
Собственно вот. Немного обрезал от мусора
Сообщений: 343
Тем: 4
Зарегистрирован: Jan 2011
Репутация:
2,824
Код: Self.Priority:=tpHighest; //Стартуем с высоким приоритетом
Эта строчка от лукавого.
Код: SaveFile:=TSaveFile.Create(stream,path);
Application.ProcessMessages;
Тебе надо в цикле проверять завершение потока, попустно делая Application.ProcessMessages, чтобы GUI не зависало. Заюзай TEvent.
Сообщений: 5,863
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
G1ta0, я вообще хотел сделать так:
файл скачивается в stream и потом создается thread, который записывает этот stream на диск, а в это время программа качает уже следующий файл
Сообщений: 220
Тем: 19
Зарегистрирован: Oct 2011
Репутация:
2,462
Странная постановка задачи.
Зависает скорее не сохранение, а загрузка файла. Не может файл скачиваться быстрее, чем записываться на локальный диск. Скачку и сохранение надо делать в отдельном потоке с информированием формы через SendMessage. Типа TDownloader.Create('http://example.com/file.zip', 'C:\file.zip', frmMain.Handle). Объект TDownloader в процессе шлет форме сообщения о прогрессе, в случае ошибки и при завершении загрузки.
Цитата:Тебе надо в цикле проверять завершение потока, попустно делая Application.ProcessMessages, чтобы GUI не зависало. Заюзай TEvent.
Зачем делать новый поток, если основной поток будет в цикле ждать его завершения? При вызове Application.ProcessMessages форма конечно будет перерисовываться, и кнопки будут нажиматься, но по-моему так делать не стоит.
hLaPEx, Evermore, hAuthD, L2on, ...
Сообщений: 5,863
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
08-22-2012, 06:13 PM
(Сообщение последний раз редактировалось: 08-22-2012, 06:19 PM Zubastic.)
Hint Написал:Странная постановка задачи.
Зависает скорее не сохранение, а загрузка файла. Не может файл скачиваться быстрее, чем записываться на локальный диск. Скачку и сохранение надо делать в отдельном потоке с информированием формы через SendMessage. Типа TDownloader.Create('http://example.com/file.zip', 'C:\file.zip', frmMain.Handle). Объект TDownloader в процессе шлет форме сообщения о прогрессе, в случае ошибки и при завершении загрузки.
Зачем делать новый поток, если основной поток будет в цикле ждать его завершения? При вызове Application.ProcessMessages форма конечно будет перерисовываться, и кнопки будут нажиматься, но по-моему так делать не стоит. Подвисает именно сохранение (двигать окошко нельзя).
Я делал через Indy Http тк там можно считать % сколько скачалось и прочее. А потом стрим сохранял на диск.
Добавлено через 5 минут
G1ta0 Написал:Код: Self.Priority:=tpHighest; //Стартуем с высоким приоритетом
Эта строчка от лукавого. Переделывал под себя, вроде как не влияет..
G1ta0 Написал:Код: SaveFile:=TSaveFile.Create(stream,path);
Application.ProcessMessages;
Тебе надо в цикле проверять завершение потока, попустно делая Application.ProcessMessages, чтобы GUI не зависало. Заюзай TEvent. Файл качается, но на диске или создается файл в 0 метров или же вообще пустота.
Чтобы не зависало использую антифриз.
Сообщений: 343
Тем: 4
Зарегистрирован: Jan 2011
Репутация:
2,824
Hint Написал:Зачем делать новый поток, если основной поток будет в цикле ждать его завершения? При вызове Application.ProcessMessages форма конечно будет перерисовываться, и кнопки будут нажиматься, но по-моему так делать не стоит.
Ясен пень не стоит, но я смотрю на данный кусок кода, там же Stream.Free после создания потока, значит надо ждать пока запишется. Иначе объект, с которым поток работает невалидным будет.
Сообщений: 5,863
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
G1ta0 Написал:Ясен пень не стоит, но я смотрю на данный кусок кода, там же Stream.Free после создания потока, значит надо ждать пока запишется. Иначе объект, с которым поток работает невалидным будет. Вот я хочу, чтобы программа не ждала, а качала следующую часть, сохраняя в фоновом режиме файл.
Код: procedure TForm1.Download(obj,path:string);
var Stream:TMemoryStream;
SaveFile:TSaveFile;
begin
Stream:=TMemoryStream.Create; //выделение памяти под переменную
try
//obj:='http://files-w2.asterios.tm:88/high_five_asterios.7z';
idHTTP1.Get(obj, Stream); //загрузка в поток данных из сети
SaveFile:=TSaveFile.Create(stream, path);
[B]SaveFile.Execute;[/B]
Application.ProcessMessages;
except
//
end;
Stream.Free; //освобождаем память
end;
Если добавляю выделенную строчку, то все работает. Почему иначе не сохраняет (насколько я понял, при создании потока он автоматически начинает выполняться).
Сообщений: 343
Тем: 4
Зарегистрирован: Jan 2011
Репутация:
2,824
Zubastic Написал:Если добавляю выделенную строчку, то все работает. Почему иначе не сохраняет (насколько я понял, при создании потока он автоматически начинает выполняться).
Stream.Free убери тогда из метода, и поставь в деструктор потока. Ты передаешь объект, который невалиден становится после старта потока.
|