Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как грамотно организовать копирование файлов по локалке. (+) [D7, WinXP]


Страницы:   1 2

EarlVadim ©   (2006-01-18 10:42:00) 

Есть необходимость периодически опрашивать удалённые хосты (с доступом естессно) на наличие в сети, и в положительном случае, копировать с них определённый файл.

Сейчас тупо используеься COPYFILE(SFN,TFN); Проблема в том, что процесс копирования файла "примораживает" программу, а если хост недоступен, то это уже на 5-10 секунд "заморозка". Ни свернуть, ни закрыть, ничего.  Файл небольшой - до 100Кб.

Как это НАДО делать, чтобы процесс опроса-копирования действительно был ФОНОВЫМ?


EarlVadim   (2006-01-25 11:20:00) [21]

Thread.Resume; я пробовал и раньше.  Сейчас сделал все как написано.
Проставил два брейка.
Результат:

Ни на BEGIN  в Execute, ни на BEGIN в ProcessFile выполнение не останавливается, -> ход выполнения до них не добирается.
Может D7 глючит?  Хотя в другой версии той же проги у меня работает код без WaitFor.  Но та версия сама по себе меня не устраивает.

Придётся с нуля проект создавать, видимо.


Digitman   (2006-01-25 09:38:00) [22]


> без Thread.WaitFor; Execute вообще не факт что получит управление


получит, если поток не создан как suspended.
и это факт.

установи брейкпойнт

procedure MyThread.Execute;
begin //<- ЗДЕСЬ
..
end;

вызови

Thread := MyThread.Create(..., False);

и убедись в "факте".

Единственное что я упустил в [11] и что важнов том контексте :

//поток создается как suspended для того чтобы перед началом его выполнения можно было назначить нужные нам св-ва

Thread := MyThread.Create(... конкретный URL файла .., True);  

//поток должен разрушить себя сам после завершения выполнения
Thread.FreeOnTerminate := True;

//назначение обработчика события
 Thread.OnTerminate := ProcessFile; //назначенный обработчик события OnTerminate будет вызван в осн.потоке процесса сразу после завершения метода MyThread.Execute;

//и наконец "пробуждаем" поток !
 Thread. Resume;


EarlVadim   (2006-01-24 18:23:00) [23]

Скажу больше,  без Thread.WaitFor; Execute вообще не факт что получит управление.  У меня в 4-х вариантах пробы потока, так вот работают потоки в 2-х, а в 2-х других - НЕТ.  Все вызовы идентичны, голова уже пухнет...


EarlVadim   (2006-01-24 17:47:00) [24]

Digitman ©   (24.01.06 17:26) [13]

По шагам прошёл,  не передаётся выполнение туда и всё тут.
В общем, в печали я.


Digitman   (2006-01-24 17:26:00) [25]


> EarlVadim ©   (24.01.06 17:12) [12]


отладчик тебе в руки


EarlVadim   (2006-01-24 17:12:00) [26]

Digitman ©   (20.01.06 13:45) [11]

Нифига не работает такой вариант.
ProcessFile - не выполняется.


Digitman   (2006-01-20 13:45:00) [27]


> Или есть другие способы?


Конечно же есть.

WaitFor был простейшим решением для оригинального примера в [7].

В изложенном же в [10] случае можно поступить, например, так:

MyThread = class(TThread)
private
 FParameter: String;
 FResult: String;  
protected
 procedure Execute; override;
public
 constructor Create(DownloadURL: String; Suspended: Boolean);
 property DownloadedFileName: String read FResult;
end;

..

constructor MyThread.Create(DownloadURL: String; Suspended: Boolean);
begin
FParameter := DownloadURL;
inherited Create(Suspended);
end;

procedure MyThread.Execute;
begin
try
.. попытка закачки файла по локатору в FParameter ..
 FResult := ... полный путь к закачанному файлу .. //закачка успешна
except
  .. закачка неуспешна ..
end;
end;

...

Procedure TMainForm.ProcessFile(Sender: TObject);
begin
  with TMyThread(Sender) do begin
    if DownloadedFileName <> '' then //закачка успешна
      Labels[..].Caption:= DownloadedFileName;// эмуляция "обработки файла" для примера
  end;
end;
 

  Thread := MyThread.Create(... конкретный URL файла .., True);
  Thread.FreeOnTerminate := True;
  Thread.OnTerminate := ProcessFile; //назначенный обработчик события OnTerminate будет вызван в осн.потоке процесса сразу после завершения метода MyThread.Execute;
//   Labels[iz].Caption:= Thread.ExecResult;
//   Thread.Destroy;


EarlVadim   (2006-01-20 10:15:00) [28]

Digitman ©   (19.01.06 09:59) [8]

Этсамое.... Ну прикрутил я всё в свою прогу, все работает, но эффекта положительного нет. Все дело в Thread.WaitFor;  
Обясняю:  в теле MainForm организован цикл  "по всем хостам читать файл и данные файла хитрым образом обрабатывать". Чтение файлов я воткнул в поток, а вот обработка у меня в MainForm. Так вот, пока файл по сети читаясь тупит, программа, следуя WaitFor тоже приморожена. Но если WaitFor убрать, то естессно нифига неработает.  Какой для этого выход?
Мне видится так, что я должен в поток переместить всю процедуру (и чтения файлов и их обработку и вывод результатов в окно программы).

Или есть другие способы?


EarlVadim   (2006-01-19 10:04:00) [29]

Digitman ©   (19.01.06 09:59) [8]

Спасибо...  Ведь как все просто, но сам не допрёшь...


Digitman   (2006-01-19 09:59:00) [30]

MyThread = class(TThread)
private
  FParameter: Integer;
  FResult: String;  
protected
  procedure Execute; override;
public
  constructor Create(Parameter: Integer);
  property MyResult: String read FResult;
end;

..

constructor MyThread.Create(Parameter: Integer);
begin
 FParameter: Integer;
 inherited Create(False);
end;

procedure MyThread.Execute;
begin
  FResult := IntToStr(FParameter);
end;

...

Procedure TMainForm.ReadData(Sender: TObject);
Var iz : integer;
begin
  For iz:= 0 to 9 do BEGIN
   Thread := MyThread.Create(iz);
   Thread.WaitFor;
   Labels[iz].Caption:= Thread.ExecResult;
   Thread.Destroy;
  END;
end;


EarlVadim   (2006-01-19 09:37:00) [31]

2 Digitman ©   (18.01.06 17:32) [6]

Ну с принципом я в общем-то разобрался.
Простая прога с потоком - работает.
Вставляю теже самые компоненты, процедуры, классы в свою программу,  поток не работает. (Хотя в теле потока для начала все предельно просто)


unit MyThreadU;

interface

uses
 Classes, Windows, SysUtils, Variants;

type
 MyThread = class(TThread)
 private
   { Private declarations }
 protected
   procedure Execute; override;
 public
   i1  : integer;
   s1 : string;
 end;

implementation

procedure MyThread.Execute;
begin

     s1:= IntToStr(i1);

end;

end


Соответственно в главной проге

Procedure TMainForm.ReadData(Sender: TObject);
Var iz : integer;
begin
   Thread := MyThread.Create(true);
   Thread.Priority := tpLowest;
   Thread.FreeOnTerminate:= false;  
   For iz:= 0 to 9 do BEGIN
      Thread.i1:= iz;
      Thread.Resume;
      Labels[iz].Caption:= Thread.s1;
   END;
   Thread.Destroy;
end;


Чтоже у меня не правильно? Пробовал разные варианты. И Create/Destroy ставил в тело цикла. И Create(false) писал - ничего.  "s1' всегда = '';


Digitman   (2006-01-18 17:32:00) [32]

реализуй код доп.потока, который собственно и будет заниматься копированием файла.

ссылку на местоположение файла передавай параметром при конструировании потока


EarlVadim   (2006-01-18 12:41:00) [33]

2 Fay ©  (18.01.06 11:45) [4]

Я тут в сети нашёл пример создания приложения с двумя потоками.
http://rusasdatabase.narod.ru/threads.html

Все работает, все ОК.  Но вот вопрос, как прикрутить это все себе.
Объясните принцип.  Вся программа должна быть одним потоком, а CopyFile - вторым,  Или просто создать в программе один поток с CopyFile?


Fay   (2006-01-18 11:45:00) [34]

2 EarlVadim ©   (18.01.06 11:39) [3]
CreateThread | свой наследник TThread


EarlVadim   (2006-01-18 11:39:00) [35]

Не сталкивался.
Если не в лом, как делать?


Fay   (2006-01-18 11:37:00) [36]

2 EarlVadim ©   (18.01.06 10:42)
Вытащи в отдельный поток.


EarlVadim   (2006-01-18 10:45:00) [37]

Да, чуть не забыл,  Сеть- MS на TCP/IP


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо