Форум: "Начинающим";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];
Вниз"Зависание" интерфейса программы во время работы InternetReadFile Найти похожие ветки
← →
kilonet © (2006-12-01 00:06) [0]в цикле вызывается несколько раз функция InternetReadFile, при этом интерфейс программы "зависает", как можно этого избежать?
Пробовал Application.ProcessMessages вызывать вместе с этой функцией - эффекта никакого.
← →
Dmitrij_K (2006-12-01 00:11) [1]Вынеси работу в отдельный поток.
Пример есть в демках
← →
kilonet © (2006-12-01 22:45) [2]сделал скачивание отдельным потоком
всё равно проблема остаётся
← →
Kolan © (2006-12-01 22:50) [3]> Application.ProcessMessages вызывать вместе с этой функцией
А надо не вместе а внутри нее вызывать. А поток- это то чтотеб надо.
← →
Джо © (2006-12-01 23:08) [4]> [2] kilonet © (01.12.06 22:45)
> сделал скачивание отдельным потоком
> всё равно проблема остаётся
Показывай код тогда.
← →
kilonet © (2006-12-02 00:41) [5]
procedure TMainForm.btnLoadFileClick(Sender: TObject);
var
DT: TDownloadThread;
begin
DT := TDownloadThread.Create(True);
DT.FileURL := URL.Text;
DT.SaveDialog := SaveDialog1;
DT.Resume;
end;
//--------------------------------------------------------------
unit DownloadThread;
interface
uses
Classes, Dialogs, WinInet, SysUtils, Forms;
type
TDownloadThread = class(TThread)
private
{ Private declarations }
function GetInetFile(const fileURL, FileName: string): boolean;
protected
procedure Execute; override;
public
FileURL: String;
FileName: String;
SaveDialog: TSaveDialog;
procedure DownloadFile;
end;
implementation
procedure TDownloadThread.DownloadFile;
begin
if SaveDialog.Execute then
GetInetFile(FileURL, SaveDialog.FileName);
end;
procedure TDownloadThread.Execute;
begin
{ Place thread code here }
Synchronize(DownloadFile);
end;
function TDownloadThread.GetInetFile(const fileURL,
FileName: string): boolean;
const
BufferSize = 1024;
var
hSession, hURL: HInternet;
Buffer: array[1..BufferSize] of Byte;
BufferLen: Cardinal;
f: file;
sAppName: string;
errorCode: Cardinal;
errorBuffer: String[128];
bufferLength: Cardinal;
begin
sAppName := ExtractFileName(Application.ExeName);
hSession := InternetOpen(PChar(sAppName),
INTERNET_OPEN_TYPE_PRECONFIG,
nil, nil, 0);
try
hURL := InternetOpenURL(hSession,
PChar(fileURL),
nil,0,0,0);
try
AssignFile(f, FileName);
Rewrite(f,1);
repeat
InternetReadFile(hURL, @Buffer,
SizeOf(Buffer), BufferLen);
BlockWrite(f, Buffer, BufferLen);
until
BufferLen = 0;
CloseFile(f);
Result:=True;
finally
InternetCloseHandle(hURL)
end;
finally
InternetCloseHandle(hSession)
end;
end;
end.
← →
Орион © (2006-12-02 00:45) [6]:) ты вызываешь процедуру скачивания GetInetFile в контексте основного потока.
← →
Орион © (2006-12-02 00:46) [7]точней функцию :)
← →
Орион © (2006-12-02 00:47) [8]ключевые моменты:
procedure TDownloadThread.DownloadFile;
begin
if SaveDialog.Execute then
GetInetFile(FileURL, SaveDialog.FileName);
end;
procedure TDownloadThread.Execute;
begin
{ Place thread code here }
procedure TDownloadThread.DownloadFile;
begin
if SaveDialog.Execute then
GetInetFile(FileURL, SaveDialog.FileName);
end;
procedure TDownloadThread.Execute;
begin
{ Place thread code here }
Synchronize(DownloadFile);
end;(DownloadFile);
end;
← →
Джо © (2006-12-02 00:49) [9]> Synchronize(DownloadFile);
Ей-богу, я бы собственными руками удавил этого "учителя", который научил пол-Рунета такому идиотизму :)
2 kilonet. Ну нельзя же бездумно копировать подходы из сомнительных книжонок. Syncronize выполняет указанный метод в контексте ОСНОВНОГО потока, он, даже по названию видно, используется для синхронизации выполнения. Убирай его.
← →
Anatoly Podgoretsky © (2006-12-02 00:49) [10]> kilonet (02.12.2006 0:41:05) [5]
Архангелького начитался?
← →
Германн © (2006-12-02 01:25) [11]
> Джо © (02.12.06 00:49) [9]
>
> > Synchronize(DownloadFile);
>
> Ей-богу, я бы собственными руками удавил этого "учителя",
> который научил пол-Рунета такому идиотизму :)
Даже ИШ это не смог сделать :-(
← →
Германн © (2006-12-02 01:40) [12]Но судя по сборнику статей на сайте, это в некоей мере смог сделать ЦЧ. :-)
Той статьи я не нашел на нашем сайте.
← →
Джо © (2006-12-02 01:44) [13]> [12] Германн © (02.12.06 01:40)
> Но судя по сборнику статей на сайте, это в некоей мере смог
> сделать ЦЧ. :-)
А кто этот аббревиированный герой? :)
← →
Германн © (2006-12-02 02:45) [14]
> А кто этот аббревиированный герой? :)
>
Ну. Не буду я расшифровывать, раз уж ты сам не знаешь. :-) Тем более, что я не знаю точно, кто он сейчас. :-)
Но той статьи Кариха Николая, вроде уже нет на сайте.
← →
kilonet © (2006-12-02 11:00) [15]всем спасибо!
> Архангелького начитался?
вобще-то Delphi 7 Developer"s Guide)
> Ну нельзя же бездумно копировать подходы из сомнительных
> книжонок.
можно поподробнее плиз, как используется Synchronize, и почему в моём случае его использование приводит к нежелательным последствиям?
← →
Джо © (2006-12-02 12:27) [16]> [15] kilonet © (02.12.06 11:00)
> можно поподробнее плиз, как используется Synchronize, и
> почему в моём случае его использование приводит к нежелательным
> последствиям?
Synchronize выполняет указанный метод потока в контексте основного потока. И зачем нужно было городить доп. поток, если основные свои действия он все равно производит в основном? ;)
Synchronize, в частности, часто используется в случаях, когда нужно вывести результаты работа потока в визуальные компоненты на форме ибо VCL, по большому счету — непотокобезопасна, т.е., обращения к компонентам не должны производиться из доп. потоков (грубо, но примерно так).
← →
kilonet © (2006-12-02 12:44) [17]
> И зачем нужно было городить доп. поток, если основные свои
> действия он все равно производит в основном?
я так понимаю, чтобы интерфейс не "зависал", нет?
всё равно непонятно, почему инерфейс зависает при использовании Synchronize?
← →
Джо © (2006-12-02 12:50) [18]> [17] kilonet © (02.12.06 12:44)
>
> > И зачем нужно было городить доп. поток, если основные
> свои
> > действия он все равно производит в основном?
>
> я так понимаю, чтобы интерфейс не "зависал", нет?
> всё равно непонятно, почему инерфейс зависает при использовании
> Synchronize?
Так. Попробую еще раз. Чтобы "интерфейс" не зависал, нужно действия по загрузке файла производить в дополнительном потоке. Ты их производишь в основном. Понятно, "почему интерфейс зависает"? Потому, что он их производит в основном. Производит в основном.
← →
Leonid Troyanovsky © (2006-12-02 12:54) [19]
> kilonet © (02.12.06 12:44) [17]
> всё равно непонятно, почему инерфейс зависает при использовании
> Synchronize?
> Джо © (02.12.06 12:27) [16]
> Synchronize выполняет указанный метод потока в контексте
> основного потока.
На всякий случай, добавлю, что за интерфейс отвечает
основной поток.
--
Regards, LVT.
← →
Джо © (2006-12-02 13:06) [20]Показываю на примере.
Вот класс трэда, который основные действия (в данном случае, просто "накручивание" счетчика в цикле) производит в доп. потоке. И только для того, чтобы вывести текущий результат работы в компонент TMemo он использует Synchronize (ибо, как было сказано, обращение к компонентам следует, в общем случае, производить из основного, а не доп. потока).TMyThread = class(TThread)
private
FMemo: TMemo;
FCurrentStage: Integer;
protected
procedure OutputCurrentStage;
procedure Execute; override;
public
property Memo: TMemo read FMemo write FMemo;
end;
implementation
procedure TMyThread.Execute;
var
I: Integer;
begin
for I := 1 to 100000 do
begin
FCurrentStage := I;
Synchronize(OutputCurrentStage);
end;
end;
procedure TMyThread.OutputCurrentStage;
begin
if Assigned (FMemo) then
FMemo.Lines.Add(IntToStr(FCurrentStage))
end;
А вот класс трэда, который ВСЮ свою работу производит в основном потоке. Смысла в этом — никакого (как и в твоем коде). Ибо "зачем нужно было городить доп. поток, если основные свои действия он все равно производит в основном?".TMyThread2 = class(TThread)
private
FMemo: TMemo;
FCurrentStage: Integer;
protected
procedure OutputCurrentStage;
procedure Execute; override;
public
property Memo: TMemo read FMemo write FMemo;
end;
implementation
procedure TMyThread2.Execute;
begin
Synchronize(OutputCurrentStage);
end;
procedure TMyThread2.OutputCurrentStage;
var
I: Integer;
begin
for I := 1 to 100000 do
begin
FCurrentStage := I;
if Assigned (FMemo) then
FMemo.Lines.Add(IntToStr(FCurrentStage))
end;
end;
Код для тестирования следующий, первый поток:procedure TForm1.Button1Click(Sender: TObject);
begin
with TMyThread.Create(True) do
begin
Memo := Memo1;
FreeOnTerminate := True;
Resume
end;
end;
Второй поток:procedure TForm1.Button2Click(Sender: TObject);
begin
with TMyThread2.Create(True) do
begin
Memo := Memo1;
FreeOnTerminate := True;
Resume
end;
end;
В первом случае — интерфейс "не застывает", позволяя двигать форму по экрану, нажимать кнопки и т.д.
Во втором — пока поток не закончит свою работу — интерфейс "замораживается". Ибо все действия производятся в основном потоке.
Надеюсь, теперь все стало ясно.
← →
sniknik © (2006-12-02 13:16) [21]> всё равно непонятно, почему инерфейс зависает при использовании Synchronize?
основной поток это тротуар, дополнительный дорога, ты везешь кудато тещу по дополнительному, но почемуто на нее обиделся и выгнал на основной (тротуар), ну а т.к. не можеш ехать дальше быстро (жена ждет тещу а не тебя, везеш то ты ее) то сам пристраиваешься чуть позади нее.
и тут же начинаешь возмущаться и чего это машина так долго едет!? и главное а почему это хвост позади тебя образовался никто (интерфейс) дальше ешать не хочет... (дорога однорядная) ;о)
(еще более грубо, но надеюсь понятнее)
← →
kilonet © (2006-12-04 14:36) [22]
> Надеюсь, теперь все стало ясно.
ммм...
то есть Synchronize как бы выносит работу процедуры-аргумента в основной поток?
← →
Джо © (2006-12-04 14:46) [23]> [22] kilonet © (04.12.06 14:36)
>
> > Надеюсь, теперь все стало ясно.
>
> ммм...
> то есть Synchronize как бы выносит работу процедуры-аргумента
> в основной поток?
Ну вот, именно об этом последние постов 5-6 :)
← →
kilonet © (2006-12-04 15:03) [24]ааа)))
спасибо за помощь!!
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.048 c