Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.24;
Скачать: CL | DM;

Вниз

"Зависание" интерфейса программы во время работы 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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.061 c
15-1164784036
StriderMan
2006-11-29 10:07
2006.12.24
Простой графический редактор


2-1165417344
Lubacha
2006-12-06 18:02
2006.12.24
я сделала программу на делфи. почему после того как из нее выход


15-1164804697
iamdanil
2006-11-29 15:51
2006.12.24
Frontpage - удаленный веб-узел


15-1165248006
oldman
2006-12-04 19:00
2006.12.24
Наши опять взяли Кубок Девиса...


1-1163014103
gosha73
2006-11-08 22:28
2006.12.24
перехват WM_SIZE для TApplication