Форум: "Начинающим";
Текущий архив: 2011.01.09;
Скачать: [xml.tar.bz2];
ВнизКак остановить закачку в IdHttp? Найти похожие ветки
← →
vegarulez (2010-10-12 10:30) [0]Привет всем мастерам!
Вопрос состоит в следующем в основном потоке создаётся дополнительный - который скачивает с сервера нужный мне файл, и докачивает его, потом если вдруг соединение к интернету было разорвано. Вопрос заключается в следующем - как принудительно отключить скачивание, по нажатию на кнопоку.
Т.к. там происходит взаиможействи на уровне idhttp в процедуре idHTTP1Work
пытаюсь сделать terminate потока - но закачка всёравно продолжается. подскажите.
...
const
MY_MESS = WM_USER + 1;
type
TFormMain = class(TForm)
ProgressBar1: TProgressBar;
Edit1: TEdit;
Edit2: TEdit;
Button3: TButton;
Button8: TButton;
...
type
TDownLoadfile = class(TThread)
private
FSourceFile, FSourceURL: string;
FSizeFile: Dword;
IdHTTP1:TidHttp;
protected
procedure Execute;override;
public
property SourceURL:string read FSourceURL write FSourceURL;
property SourceFile:string read FSourceFile write FSourceFile;
property SizeFile:Dword read FSizeFile write FSizeFile;
procedure idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
procedure idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
procedure idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
end;
...
procedure TFormMain.Button3Click(Sender: TObject);
begin
SaveDialog1.FileName:=copy(Edit1.Text,LastDelimiter("\/",Edit1.Text)+1,maxint);
if SaveDialog1.Execute then
Edit2.Text:=SaveDialog1.FileName;
end;
procedure TFormMain.MyProgress(var msg: TMessage);
begin
case msg.WParam of
0:
begin
{label4.Caption:= formatfloat("0.00",msg.LParam / 1024 / 1024) +" мб ("+inttostr(msg.LParam)+")";
L_P_Num_1.Caption:= formatfloat("0.00",(RestartPos+msg.LParam) / 1024 / 1024) +" мб ("+inttostr(RestartPos+msg.LParam) +")";}
ProgressBar1.Max:=RestartPos+msg.LParam;
ProgressBar1.Position:=0;
end;
1:
begin
{label5.Caption:=formatfloat("0.00",msg.LParam / 1024 / 1024)+" мб ("+inttostr(msg.LParam)+")";
label10.Caption:= formatfloat("0.00",(RestartPos+msg.LParam) / 1024 / 1024) +" мб ("+inttostr(RestartPos+msg.LParam)+")"+" [ "+formatfloat("0",((RestartPos+msg.LParam)/ProgressBar1.Max*100)) +"% ]";}
ProgressBar1.Position:=RestartPos+msg.LParam;
end;
end;
end;
procedure TFormMain.thrTerminate(Sender: TObject);
begin
ShowMessage("Готово");
Button8.Enabled:=true;
end;
procedure TDownLoadfile.idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);
begin
PostMessage(Application.MainForm.Handle,MY_MESS,1,AWorkCount);
end;
procedure TDownLoadfile.idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Integer);
begin
PostMessage(Application.MainForm.Handle,MY_MESS,0,AWorkCountMax);
end;
procedure TDownLoadfile.idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
//
end;
procedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.EndWork;
end;
{ TDownLoadfile }
procedure TDownLoadfile.Execute;
var
FileDate: TDateTime;
FileType: string;
SourceFileSize: Dword; // размер исходного файла который собираемся скачивать
fDownloadStream: TFileStream;
begin
IdHTTP1:=TIdHTTP.Create(nil);
IdHTTP1.OnWork:=IdHTTP1Work;
IdHTTP1.OnWorkBegin:=IdHTTP1WorkBegin;
IdHTTP1.OnWorkEnd:=IdHTTP1WorkEnd;
IdHTTP1.ProtocolVersion := pv1_1; //pv1_1
IdHTTP1.HandleRedirects := True;
IdHTTP1.Head(SourceURL);
SourceFile :=IdHTTP1.Response.RawHeaders.Text; // Values["ETag"], """, "", [rfReplaceAll]), "-", "", [rfReplaceAll]); //
SourceFile := StringReplace(StringReplace(IdHTTP1.Response.RawHeaders.Values["ETag"], """, "", [rfReplaceAll]), "-", "", [rfReplaceAll]); // Text;
SourceFile := IdHTTP1.URL.Document;
SourceFileSize := IdHTTP1.Response.ContentLength;
if SourceFileSize>SizeFile then // значит файл не докачан или его нет вовсе.
Begin
FileDate := IdHTTP1.Response.LastModified;
FileType := IdHTTP1.Response.ContentType;
if FileExists(IdHTTP1.URL.Document) then
begin
fDownloadStream := TFileStream.Create(SourceFile, fmOpenReadWrite);
fDownloadStream.Position:=SizeFile;
Idhttp1.Request.Range:=Format("%d-%d",[fDownloadStream.Position,SourceFileSize]);
fDownloadStream.Seek(fDownloadStream.Position,soFromBeginning);
end
else
begin
fDownloadStream := TFileStream.Create(SourceFile, fmCreate);
fDownloadStream.Seek(0,soFromBeginning); //
end;
IdHTTP1.Request.ContentType := FileType;
IdHTTP1.Request.ContentRangeStart := fDownloadStream.Position;
IdHTTP1.Request.ContentRangeEnd := SourceFileSize;
try
IdHTTP1.Get(SourceURL,fDownloadStream);
finally
fDownloadStream.Free;
IdHTTP1.Free;
end;
End
else
terminate;
end;
function GetFileSize(FileName: String): Integer;
var
FS: TFileStream;
begin
try
FS := TFileStream.Create(Filename, fmOpenRead);
except
Result := -1;
end;
if Result <> -1 then Result := FS.Size;
FS.Free;
end;
procedure TFormMain.Button8Click(Sender: TObject);
var
t:TDownLoadfile;
begin
Button8.Enabled:=false;
//Создадим класс потока.
//Поток для начала будет остановлен
t:=TDownLoadfile.Create(true);
//Передадим параметры потоку
t.SourceURL:=Edit1.Text;
t.SourceFile:=Edit2.Text;
RestartPos:=0;
//Если на винте есть файл то считаем, что нужно докачивать
if FileExists(Edit2.Text) then
RestartPos:=GetFileSize(Edit2.Text); //*128
t.SizeFile:=RestartPos;
//Поток должен удалить себя по завершению своей работы
t.FreeOnTerminate:=true;
t.OnTerminate:=thrTerminate;
//И запустим его на закачку.
t.Resume;
//Теперь с процедуры мы выйдем, но поток работает
//и живёт своей жизней
end;
← →
Сергей М. © (2010-10-12 11:06) [1]Из другого потока вызови IdHTTP.Socket.Close, тогда IdHTTP.Get() возвратит управление с соотв.исключением
← →
vegarulez (2010-10-12 11:16) [2]перенёс описание idhttp1 в type
type
TDownLoadfile = class(TThread)
private
FSourceFile, FSourceURL: string;
FSizeFile: Dword;
IdHTTP1:TidHttp;
protected
procedure Execute;override;
public
property SourceURL:string read FSourceURL write FSourceURL;
property SourceFile:string read FSourceFile write FSourceFile;
property SizeFile:Dword read FSizeFile write FSizeFile;
procedure idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
procedure idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
procedure idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
end;
и пытаюсь
его остановить как ты посоветовалprocedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.Socket.Close;
end;
вывваливается ошибка (
← →
DiamondShark © (2010-10-12 12:10) [3]
> вывваливается ошибка (
Где? Если здесь:
IdHTTP1.Get(SourceURL,fDownloadStream);
то так и должно быть.
← →
Сергей М. © (2010-10-12 12:46) [4]
> перенёс описание idhttp1 в type
>
Нафига ?
Достаточно у TDownLoadfile объявить публ.метод а-ля AbortConnection, в теле которого вызывать IdHTTP.Socket.Close
← →
vegarulez (2010-10-13 10:14) [5]Вроде всё сделал как ты посоветовал.
Но ничего не получается... ((
Посмотри плиз, если не сложно - я отправил тестовый примерчик с которым работаю на
http://zalil.ru/29807305
весит 10 кб
У меня вываливается ошибка - Access violation at address ... in module...
← →
sniknik © (2010-10-13 10:28) [6]> Access violation at address ... in module...
procedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.Socket.Close;
end;
объект t не инициализирован/не существует.
← →
Сергей М. © (2010-10-13 11:04) [7]procedure TForm1.Button3Click(Sender: TObject);
var
t:TDownLoadfile;
begin
t.AbortConnection;
end;
в t мусор
← →
vegarulez (2010-10-13 11:10) [8]я же определяю переменную t как TDownLoadfile, иначе как мне из основного потока обращаться к элементам дочернего потока.
из примера который скинул на залил.ру:procedure TDownLoadfile.AbortConnection();
begin
idhttp1.Socket.Close;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
t:TDownLoadfile;
begin
t.AbortConnection;
end;
← →
vegarulez (2010-10-13 11:11) [9]Сергей М. © (13.10.10 11:04) [7]
а как тогда правильно реализовать???
← →
Сергей М. © (2010-10-13 11:23) [10]1. Сделать t полем класса формы, а не лок.переменной
2. В обработчике OnTerminate нилить t:
procedure TForm1.thrTerminate(Sender: TObject);
begin
t := nil;
ShowMessage("Готово");
Button4.Enabled:=true;
end;
3.
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(t) then
t.AbortConnection;
end;
← →
vegarulez (2010-10-13 16:35) [11]давай по пунктам
что значит сделать полем класса формы?
т.е. объявить в type относящемуся к форме, т.е. к unit1 в public секции
t:Form1 ?
если сделать так, то процедура AbortConnection должна быть объявлена тоже в type относящемуся к unit1, чтобы компилятор её увидел и не сругнулся, соответсвенно если в этой процедуре будет обращаение к idhttp1 объявленному в type относящемуся к TDownLoadfile - то он его не видит и ругается... (
прошу не кидать в меня кирпичом - но реально ничего не понял (((
← →
vegarulez (2010-10-13 16:38) [12]если же t объявлять в type относящемуся к unit1
t:TDownLoadfile
то он пока ещё не видит объявления TDownLoadfile которое будет ниже и тоже ругается на переменную t...
p.s. про кирпичи - тоже что в предыдущем посте...
← →
Сергей М. © (2010-10-13 16:55) [13]TForm1 = class(TForm)
..
private
t:TDownLoadfile;
..
end;
....
t := TDownLoadfile.Create(...);
← →
Palladin © (2010-10-13 20:35) [14]по-моему на этом сайте не хватает еще одной конференции
← →
Сергей М. © (2010-10-13 21:24) [15]
> Palladin © (13.10.10 20:35) [14]
"Патрепацца" ?)
← →
Palladin © (2010-10-13 21:25) [16]не )
Основная ("Начинающим" ("Никогда не закончащим"))
← →
Сергей М. © (2010-10-13 22:02) [17]
> Palladin © (13.10.10 21:25) [16]
Я понял про что ты)
Но лучше бы таки "Орешник" реанимировать)
← →
sniknik © (2010-10-15 18:27) [18]> не )
> Основная ("Начинающим" ("Никогда не закончащим"))
детский сад. с лозунгом "нас не научишь..." под песню та-ту.
← →
vegarulez (2010-10-17 14:38) [19]Сергей М. © (13.10.10 16:55) [13]
Я же написал vegarulez (13.10.10 16:38) [12]
что когда так делаю - выскакивает ошибка при компиляции.
Так какtype
TDownLoadfile = class(TThread)
private
...
end;
Описан после описния TForm1 = class(TForm)
то он ругается при компиляции наTForm1 = class(TForm)
..
private
t:TDownLoadfile;
..
end;
т.к. не знает что такое TDownLoadfile
← →
Anatoly Podgoretsky © (2010-10-17 15:13) [20]> vegarulez (17.10.2010 14:38:19) [19]
Поставь перед TDownLoadfile = class;
← →
sniknik © (2010-10-17 15:42) [21]имхо, лучше описать сам поток до формы... (какие то проблемы с тем что что форма не первая?), а еще лучше в отдельном модуле и прописать его в юзес раздела интерфасе.
← →
Плохиш © (2010-10-17 16:14) [22]
> vegarulez (17.10.10 14:38) [19]
Тебе уже предлагали нанять программиста?
← →
Palladin © (2010-10-17 16:47) [23]Предлагаю нанять программиста.
← →
Anatoly Podgoretsky © (2010-10-17 17:28) [24]Все решение перебраны и это тоже.
← →
vegarulez (2010-10-17 17:41) [25]Anatoly Podgoretsky © (17.10.10 15:13) [20]
sniknik © (17.10.10 15:42) [21]
Спасибо большое.
← →
Anatoly Podgoretsky © (2010-10-17 17:52) [26]> vegarulez (17.10.2010 17:41:25) [25]
Да не за что, мы приложили все силы.
← →
HF-Trade © (2010-10-19 07:27) [27]
> Из другого потока вызови IdHTTP.Socket.Close, тогда IdHTTP.
> Get() возвратит управление с соотв.исключением
Почему из другого потока?
Поясните почему не будет работать -
...
{В потоке}
AIdHttp := TIdHttp.Create(nil);
AIdHttp.OnWork := Form1.IdHttp1Work;
Try
Try
AIdHttp.Get(URL);
Except
end;
Finally
AIdHttp.Free;
....
{На форме}
procedure TForm1.IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
IF Start = False Then
(ASender as TIdHttp).Socket.Close;
end;
← →
HF-Trade © (2010-10-19 07:39) [28]ошибся, Work, конечно, не workend
← →
sniknik © (2010-10-19 08:10) [29]> Почему из другого потока?
а почему у тебя так же? вот Http.Get у тебя в дополнительном, а Start для остановки ты False будешь присваивать в каком? судя по всему в другом, основном.
хочешь попытайся в том же, дополнительном, посмотрим как у тебя получится.
← →
HF-Trade © (2010-10-19 08:37) [30]ммм... событие Work можно описать и в доп.потоке.
Я и спрашиваю -
1. Почему из другого потока?
2. Почему не работает код выше? хотя там из VCL закрываем сокет, он тупо висит пока не закончится ConnectionTimeout
← →
HF-Trade © (2010-10-19 08:43) [31]То что Start присвоить false из другого потока понятно(основного к примеру), ибо доп.поток висит на Get, но сама процедура Work(если она созданна в доп. потоке), должна работать и в нем?
← →
sniknik © (2010-10-19 09:32) [32]> но сама процедура Work(если она созданна в доп. потоке), должна работать и в нем?
с чего такие инсинуации? код работает там где вызван, а не там где описан.
> Я и спрашиваю -
ты навыдумывал себе "страшилок" и спрашиваешь не по тому что предлагали, а по тому, что у тебя в голове.
← →
sniknik © (2010-10-19 09:38) [33]> Почему не работает код выше?
а он действительно не работает? тогда причина однозначна - вызов Get синхронный, пока не выполнится, дрогой код в этом потоке (неважно где описан) выполнятся не будет.
(вариант когда будет, это если описан метод типа onWorkInProccess который периодически вызывается в самом Get)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.01.09;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.004 c