Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с потоками 
:(
    Опции темы
Sergey912
Дата 8.2.2007, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 3.1.2007

Репутация: нет
Всего: нет



Сделал программу, основная задача - работать с FTP. Подъсоеденяемся к удаленному серверу и с ним работаем.
Сделал основную форму, где находится IdFTP для работы с FTP, Memo для лога и кнопка. Нажал на кнопку - пошла загрузка.
В самом потоке:

Код

procedure TFtpUpload.UpdateConnect;
Begin
Тут все операции с файлами и обращения к FTP вида:
Form1.IdFTP1.Put('file', 'file', false);

И к обновлению лога:
Form1.RichEdit1.Lines.Add('Загружен: '+name);
end;


procedure TFtpUpload.Execute;
begin
Synchronize(UpdateConnect);
end;




В форме:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
FtpProcess:= TFtpUpload.Create(true);
FtpProcess.Priority := tpLower;
FtpProcess.FreeOnTerminate := True;
FtpProcess.Resume;
end;


Но когда я загружаю - все работает т.е. файлы загружаются, но форма тормозит по прежнему. Что я не так сделал? Файлов бывает много и мне нужно точно знать, что происходит и останавливать поток иногда и потом продолжать(это уже реализовано хранением слепка файлов на сервере, чтобы не обыскивать его самого постоянно).

Что я не так делаю? Нужно было длительный процесс сделать работаюзим автономно и контролиремо и чтобы приложение вело себя нормально, а не превращалось в непонятно окно, где лог обновляется только в конце загрузки - значит правльно потоки использовал... но почему так работает?  smile 
PM MAIL WWW   Вверх
Rennigth
Дата 8.2.2007, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76



Цитата(Sergey912 @  8.2.2007,  17:05 Найти цитируемый пост)
Synchronize(UpdateConnect);

Ну а чего ты еще ждал от Synchronize?



--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
dumb
Дата 8.2.2007, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 13
Всего: 158



Цитата(Sergey912 @  8.2.2007,  17:05 Найти цитируемый пост)
Что я не так делаю?

Цитата(Sergey912 @  8.2.2007,  17:05 Найти цитируемый пост)
Код

procedure TFtpUpload.Execute;
begin
Synchronize(UpdateConnect);
end;


1. убери свои извращения с потоком и кинь на форму TIdAntiFreeze.
2. Многопоточность - как это делается в Дельфи
PM MAIL   Вверх
Sergey912
Дата 8.2.2007, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 3.1.2007

Репутация: нет
Всего: нет



Цитата
1. убери свои извращения с потоком и кинь на форму TIdAntiFreeze.

Это поможет от проблем избавится, которые есть без потоков т.е. вообще их убрать можно?



Цитата
В какой-то степени этим можно управлять через свойства класса TIdAntiFreeze. Использование данного компонента не является обязательным, но позволяет решить проблему синхронизации соединений с визуальным интерфейсом приложения.

А вот нашел кое что кажется это уже ближе. А прервать ее как-то можно в таком состоянии без потерь?
Для потока есть свои ф-и, а вот для того, чтобы докачать последний файл вывести в лог и добавить в слепок файлов на сервере  - как это сделать т.е. чтобы по нажатию Stop эти вещи заканчивали работу и только потом прерывалась процедура?

Это сообщение отредактировал(а) Sergey912 - 8.2.2007, 17:29
PM MAIL WWW   Вверх
dumb
Дата 8.2.2007, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 13
Всего: 158



Цитата(Sergey912 @  8.2.2007,  17:24 Найти цитируемый пост)
А прервать ее как-то можно в таком состоянии без потерь?
Для потока есть свои ф-и, а вот для того, чтобы докачать последний файл вывести в лог и добавить в слепок файлов на сервере  - как это сделать т.е. чтобы по нажатию Stop эти вещи заканчивали работу и только потом прерывалась процедура?

хорошее описание. "прервать ее" - кого ее? что за  "свои ф-ии для потока"? кто есть "слепок файлов"? какие "вещи" заканчивали работу?!.

попробуй еще раз описать проблему и сделать это так, чтобы написанное было понятно не только тебе одному.  smile 
PM MAIL   Вверх
Sergey912
Дата 9.2.2007, 06:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 3.1.2007

Репутация: нет
Всего: нет



dumb,
загружаю файлы со своего компьютера на удаленный сервер.
Если я уберу поток, то загрузка будет происходить по клику по кнопке т.е. заработает процедура закачки - это и есть "ее".
Файлы закачиваются поочереди. Т.е. есть их список файлов и я каждый файл обрабатывают так, например наткнулись на папку:

Код

                              Form1.IdFTP1.MakeDir(server_url_array[Form1.ProgectList.ItemIndex]+AllFile[k].name);
                              StrAddToFile(IntToStr(id)+'.txt', AllFile[k].name+Chr(9)+AllFile[k].date);
                              Form1.RichEdit1.Lines.Add('Ïàïêà çàêà÷àíà: '+AllFile[k].name);

Закачиваю на сервер файл, потом добавляю его через StrAddToFile - процедуру в файл слепок т.е. слепок - это точный список всех файлов на сервере, чтобы знать что туда загружено и не сканировать его при необходимости - гораздо проще прочитать текстовый файл. И последнее добавляю в Memo, чтобы было наглядно видно как идет процесс.

Естественно файлов может быть очень много и мне иногда нужно остановить эту процедуру закачки. Я хочу сделать кнопку Stop или что-то в этом роде и остановить закачку файлов. Тогда мне надо, чтобы в зависимости от того, что сейчас делает процедура закачки она:

Закончила закачивать текущий файл, добавила его в список файлов на сервере и вывела в Memo, а не остановилась после того как закачает файл т.к. будут проблемы: в моем списке файла нет, а на сервер закачан.

PM MAIL WWW   Вверх
dumb
Дата 9.2.2007, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 13
Всего: 158



Sergey912, судя по твоему описанию, тебе таки нужно вернуть назад работу с потоком, но избавить ее от извращений. smile

не поленись и прочитай таки статью, на которую тебе дали ссылку.

приблизительно процедура Execute должна выглядеть так:
Код

procedure TFtpUpload.Execute;
begin
  idx := 0;
  while (not Terminated) and (idx < FileListCount) do begin
    FileName := FileList[idx];
    IdFTP.blabla(FileName);
    Save2Log(FileName);
    Synchronize(UpdateForm);
  end;
end;

procedure TFtpUpload.UpdateForm;
begin
  Form1.RichEdit1.Lines.Add('Загружен: '+FileList[idx]);
end;


чтобы остановить "закачку", нужно просто грохнуть поток:
Код

  MyThread.Terminate;


обрати внимание: поток должен быть в некотором смысле "оторван" от основной программы - т.е. все входные данные для его функционирования нужно поместить перед запуском внутрь класса TFtpUpload.
Код

MyThread := TMyThread.Create(true); // создать приостановленным
MyThread.tData1 := Form1.Data1;
MyThread.tFileList.Assign(Form1.FileList);
...
MyThread.Resume;

обращения к различным компонентам на форме делать через Synchronize. НО! нельзя всю работу запихивать туда, так как Synchronize останавливает рабочий поток, ждет пока ему дадут "войти" в основной поток(там, где рисуется форма, обрабатываются нажатия на кнопки итд) и там выполняет код указанной в его параметрах процедуры. пока выполняется эта процедура, все события формы "замирают". именно поэтому заключение всей работы потока внутрь Synchronize убивает смысл самого доп.потока. smile

ps. IdFTP лучше создавать динамически в начале Execute.

PM MAIL   Вверх
Sergey912
Дата 11.2.2007, 03:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 3.1.2007

Репутация: нет
Всего: нет



dumb, 
Все сделал точно как ты говорил, только одна проблемка. После вызова Terminate - поток прерывается и даже файл недокачался, неговоря уже о записи в файл и выдаче в Memo....

Точно так же сделал все в while:

Код

    while (not Terminated) and (idx < FileUploadCount) do
    begin
    UplStateInt := UploadState(AllFile[idx].name, AllFile[idx].date);

      if (UplStateInt = 1) and (AllFile[idx].ftype = 1) then
      Begin
      IdFTP1.Put(denwer_url+AllFile[idx].name, server_url+AllFile[idx].name, false);
      StrAddToFile(pr_id+'.txt', AllFile[idx].name+Chr(9)+AllFile[idx].date);
      Synchronize(UpdateMemo2);
      end;

    end;



Это один из случаев, когда файл является файлом (не папкой) и когда его нужно закачать. Все прервалось в итоге файл на сервере 1500кб вместо положенных 1700 и не записан в файлик  smile 

Все остальное тоже переделал, форма теперь трогается через процедуры, которые в Synchronize. Все перенес в поток, в форме ничего нет для работы потока нужного.

Поток стартую и прерываю так, на одной кнопке:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
FtpProcess := TFtpUpload.Create(true);

if FtpProcess.Suspended then
Begin
FtpProcess.Priority := tpLower;
FtpProcess.FreeOnTerminate := True;
FtpProcess.Resume;
Button1.Caption := 'Остановить';
Button2.Enabled := false;
end
else
Begin
FtpProcess.Terminate;
Button1.Caption := 'FTP-upload';
Button2.Enabled := false;
ProgectList.Enabled := true;
end;
end;



Это сообщение отредактировал(а) Sergey912 - 11.2.2007, 03:19
PM MAIL WWW   Вверх
dumb
Дата 11.2.2007, 07:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 13
Всего: 158



Цитата(Sergey912 @  11.2.2007,  03:16 Найти цитируемый пост)
После вызова Terminate - поток прерывается и даже файл недокачался, неговоря уже о записи в файл и выдаче в Memo...

странно. возможно, это из-за анти-фриза.. без полного кода тяжело сказать определенно.
(вообще говоря, анти-фриз этот нужен тогда, когда работа с "индейцами" идет из основного потока - они изнутри afair просто периодически Application.ProcessMessages вызывают, чтоб формы не умирали)
можно попробовать вместо Terminated использовать какой-нибудь свой флажок(соотв. вместо Terminate просто устанавливать этот флаг)

Цитата(Sergey912 @  11.2.2007,  03:16 Найти цитируемый пост)
Поток стартую и прерываю так, на одной кнопке:

хм. косяки. при каждом нажатии создаешь TFtpUpload...
сделай FtpProcess := nil где-нибудь при старте проги. а запускалку так:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  if FtpProcess = nil then begin
    FtpProcess := TFtpUpload.Create(true);
    FtpProcess.Priority := tpLower;
    FtpProcess.FreeOnTerminate := True;
    FtpProcess.Resume;
    Button1.Caption := 'Остановить';
  end
  else begin
    FtpProcess.Terminate;
    FtpProcess := nil;
    Button1.Caption := 'FTP-upload';
    ProgectList.Enabled := true;
  end;
end;

PM MAIL   Вверх
Sergey912
Дата 11.2.2007, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 3.1.2007

Репутация: нет
Всего: нет



Код

без полного кода тяжело сказать определенно.

Да это как бы и есть полный, не считая коннекта к БД и вызова процедуры обхода папки перед этим, а потом пошел цикл закачки...

 
Код

UploadState(AllFile[idx].name, AllFile[idx].date);

Это тоже процедура, которая проверяет есть ли файл на сервере и что с ним делать...
Вообще он из цикла просто выходит посередине, хз файл-т мог докачать хотя бы  smile 
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0575 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.