Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.059 c
4-1155821441
apic
2006-08-17 17:30
2006.12.24
Короткий путь


15-1165102323
SkySpeed
2006-12-03 02:32
2006.12.24
В чём ошибка в проекте С++?


15-1164977042
low_man
2006-12-01 15:44
2006.12.24
Помогите песенку перевести


15-1165145193
Pazitron_Brain
2006-12-03 14:26
2006.12.24
Когда по вашему мнению


15-1165320757
Gero
2006-12-05 15:12
2006.12.24
Были раньше времена…





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский