Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 3 423

Раздел: Delphi » Прочее
/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
Подскажите, пожалуйста, как можно выполнить этот код в отдельном потоке?

Приложение:
  1.  
  2.  
  3.  
  4.  
  5. unit Unit1;
  6.  
  7. interface
  8.  
  9. uses
  10. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  11. Dialogs, StdCtrls,URLMon;
  12.  
  13. type
  14. TForm1 = class(TForm)
  15. Button1: TButton;
  16. procedure Button1Click(Sender: TObject);
  17. private
  18. { Private declarations }
  19. public
  20. { Public declarations }
  21. end;
  22.  
  23. var
  24. Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.dfm}
  29. function DownloadFile(SourceFile, DestFile: string): Boolean;
  30. begin
  31. try
  32. Result := UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0, nil) = 0;
  33. except
  34. Result := False;
  35. end;
  36. end;
  37.  
  38. procedure TForm1.Button1Click(Sender: TObject);
  39. const
  40.  
  41. SourceFile = 'http://downloads.kaspersky-labs.com/trial/registered/8NGILSWTCHAPVSJ1NTX8/kav9.0.0.736ru.exe ';
  42.  
  43. DestFile = 'c:kav9.0.0.736ru.exe ';
  44. begin
  45. if DownloadFile(SourceFile, DestFile) then
  46. begin
  47.  
  48. end
  49. else
  50.  
  51. end;


Kyran29 Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Kyran29 (статус: Посетитель)
Вопрос отправлен: 20 ноября 2009, 12:14
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: DNK

Здравствуйте, Kyran29!
Это элементарно. К компилятору не ходи.

Приложение:
  1. type
  2. TForm1 = class(TForm)
  3. Button1: TButton;
  4. procedure Button1Click(Sender: TObject);
  5. private
  6. { Private declarations }
  7. public
  8. { Public declarations }
  9. end;
  10.  
  11. TLoadThread = class(TThread)
  12. protected
  13. procedure Execute; override;
  14. end;
  15.  
  16.  
  17. var
  18. Form1: TForm1;
  19.  
  20. implementation
  21.  
  22. {$R *.dfm}
  23.  
  24. function DownloadFile(SourceFile, DestFile: string): Boolean;
  25. begin
  26. try
  27. Result := UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0, nil) = 0;
  28. except
  29. Result := False;
  30. end;
  31. end;
  32.  
  33. procedure TForm1.Button1Click(Sender: TObject);
  34. begin
  35. TLoadThread.Create(False);
  36. end;
  37.  
  38. procedure TLoadThread.Execute;
  39. const
  40.  
  41. SourceFile = 'http://downloads.kaspersky-labs.com/trial/registered/8NGILSWTCHAPVSJ1NTX8/kav9.0.0.736ru.exe ';
  42.  
  43. DestFile = 'c:kav9.0.0.736ru.exe ';
  44. begin
  45. if DownloadFile(SourceFile, DestFile) then
  46. begin
  47.  
  48. end
  49. else
  50.  
  51. end;


Ответ отправил: DNK (статус: Студент)
Время отправки: 20 ноября 2009, 14:26
Оценка за ответ: 3

Ответ #2. Отвечает эксперт: Паровоз

Здравствуйте, Kyran29!

Делать как предлагает Ершов Денис нельзя. Методы VCL из вторичного потока можно вызывать только через Synchronize. Для этого нужно расширить класс TLoadThread:

TLoadThread = class(TThread)
protected
  FResult:String;
  procedure Execute; override;
  procedure ShowResult;
end;
Изменить метод Execute:
procedure TLoadThread.Execute;
const
  SourceFile = 'http://downloads.kaspersky-labs.com/trial/registered/8NGILSWTCHAPVSJ1NTX8/kav9.0.0.736ru.exe ';
  DestFile = 'c:\kav9.0.0.736ru.exe ';
begin
  if DownloadFile(SourceFile, DestFile) then
    FResult:=''Файл загружен!'
  else
    FResult:=''Ошибка при загрузке - '+ SourceFile;
    Synchronize(ShowResult);
end;
 
procedure TLoadThread.ShowResult;
begin
  ShowMessage(FResult);
end;

Ответ отправил: Паровоз (статус: 10-ый класс)
Время отправки: 20 ноября 2009, 15:15
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 10; последнее сообщение — 27 ноября 2009, 10:22; участников в обсуждении: 4.
Вадим К

Вадим К (статус: Академик), 20 ноября 2009, 12:28 [#1]:

А почему вы не смотрите те примеры, которые я раньше приводил??? там есть работа в потоке
Галочка "подтверждения прочтения" - вселенское зло.
Паровоз

Паровоз (статус: 10-ый класс), 20 ноября 2009, 15:21 [#2]:

P.S. Двойные кавычкми нужно заменить на одинарные:
FResult:='Файл загружен!'
FResult:='Ошибка при загрузке - '+ SourceFile
Вадим К

Вадим К (статус: Академик), 20 ноября 2009, 15:37 [#3]:

Что то мне подсказывает, что оба приведённых кода не будут работать правильно. Скажите честно, кто тестировал код перед отправкой?
Галочка "подтверждения прочтения" - вселенское зло.
DNK

DNK (статус: Студент), 20 ноября 2009, 16:35 [#4]:

Только не я. :)
Но код точно должен выполниться.
"Digital Networked Knight"
Вадим К

Вадим К (статус: Академик), 20 ноября 2009, 16:43 [#5]:

То, что код выполняется в главном треде, абсолютно не означает, что он должен выполняться в другом. тем более, многие ли знают, что в этом коде неявно подгружается половина ядра Internet Explorer?
Галочка "подтверждения прочтения" - вселенское зло.
Паровоз

Паровоз (статус: 10-ый класс), 20 ноября 2009, 20:07 [#6]:

1)Собственно говря нужно позаботиться об отсутствии утечек и Button1Click заменить на что-нибудь более правильное, типа
procedure TForm1.Button1Click(Sender: TObject);
var
lt:TLoadThread;
begin
lt:=TLoadThread.Create(False);
lt.FreeOnTerminate:=True;
lt.Resume;
end;
2) вызов ShowMessage без Synchronize, конечно, недопустим.
3) код на всякий случай протестировал - выполняется и файл загружается. Не вижу причин для беспокойства.
Kyran29

Kyran29 (статус: Посетитель), 22 ноября 2009, 01:24 [#7]:

Здравствуйте, Паровоз!
Подскажите пожалуйста, как теперь отразить весь процесс закачки файла, с помощью компонентов TProgressBar и TLabel.
Паровоз

Паровоз (статус: 10-ый класс), 24 ноября 2009, 23:26 [#8]:

В этом случае нужно использовать последний параметр функции UrlDownloadToFile - интерфейс IBindStatusCallBack. Создаете класс, реализующий этот интерфейс. Достаточно реализовать только одну функцию OnProgress, а все остальные можно сделать заглушками. При обработке ulStatusCode вычиcляете позицию newPos для TProgressBar как то так:
if ulStatusCode=BINDSTATUS_ENDDOWNLOADDATA then newPos:=100
else if ulProgressMax=0 then newPos:=0
     else newPos:=((ulProgress*100) div ulProgressMax);
Соответственно управляете и текстом TLabel. Если, например, оказывается, что ulStatusCode=BINDSTATUS_DOWNLOADINGDATA, то пишите в TLabel 'Загрузка...'.
Kyran29

Kyran29 (статус: Посетитель), 27 ноября 2009, 07:17 [#9]:

P.S
Здравствует Паровоз !
На форме имеется кнопка «Отменить закачку файла» подскажите, пожалуйста, как создать событие, которое завершает работу потока.
Паровоз

Паровоз (статус: 10-ый класс), 27 ноября 2009, 10:22 [#10]:

В классе, который реализует интерфейс IBindStatusCallBack вводите дополнительное поле, например, FAbort типа Boolean. Предположим, что obj - это созданный Вами для управления загрузкой экземпляр этого класса. Тогда в обработчике кнопки завершения пишите obj.FAbort:=True. Кроме того, в реализации метода OnProgress вставляете код проверки:
if FAbort then
begin
  FAbort:=False;
  Result:=E_ABORT;
  Exit;
end;

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:43
Выполнено за 0.03 сек.