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

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

Обработка файлов в потоке [D7, WinXP]


Sergey_R ©   (2005-10-05 10:48:00) 

Есть прога, которая скагирует все mp3'ки и читает из них теги. Для тысячи файлов все вроде работает быстро, а вот если сканировать всю музыку(около 9000 файлов), то что-то очень долго. Можно ли как-то выненсти чтение файлов отдельный поток и выводить индикатор прогресса (ProgressBar или чтто-нибудь типа него)


Bel   (2005-10-11 09:14:00) [1]

> Sergey_R ©   (09.10.05 12:13) [6]
>
> А зачем нужен Sleep(0)? Вроде ничего и не произойдет, если его убрать!

Произойдет передача процессорного времени другому потоку в очереди.


Digitman   (2005-10-11 08:31:00) [2]


> Sergey_R ©   (09.10.05 15:19) [12]


"так работает, а эдак не работает" ...
а отладчик на что существует, спрашивается ?!


andrexa   (2005-10-11 07:42:00) [3]

народ, потоки - псевдорешение, при кажущемся облегчении задачи они зачастую её усложняют на порядок, выводи индикатор, или в цикле показывай анимацию..... В конце концов ставьте Application.ProcessMessages
и обрабатывайте кнопку "прервать"


Zeqfreed   (2005-10-09 15:43:00) [4]

Sergey_R ©   (09.10.05 15:35) [14]
Так известно где - в 17-ой строке.


Sergey_R   (2005-10-09 15:35:00) [5]

Да где там может быть ошибка, если я всего-то добавил 2 компонента и один модуль? Исходный текст (добавленный) такой же, как я и написал!


Zeqfreed   (2005-10-09 15:31:00) [6]

Sergey_R ©   (09.10.05 15:19) [12]
У тебя ошибка в программе!


Sergey_R   (2005-10-09 15:19:00) [7]

У меня тоже все работает, если создавать новый проект! А вот если добавлять код в ГОТОВОЕ приложение, то ничего не работает! Вот это я и не понимаю...


Zeqfreed   (2005-10-09 15:09:00) [8]

Sergey_R ©   (09.10.05 15:02) [10]
Проверил - твой код с моими изменениями работает.
Проверил - твой код без моих изменений работает.


Sergey_R   (2005-10-09 15:02:00) [9]

> Как проверил?

В Edit2 ничего не выводится, а когда добавил в поток ShowMessage('aaa'); то он не появился! Dialogs в Uses писал!


Zeqfreed   (2005-10-09 14:54:00) [10]

Sergey_R ©   (09.10.05 14:47) [8]
procedure TMyThread.Execute;
var
i: Integer;
begin
FreeOnTerminate := true;
for i := 1 to 10000 do
begin
  answer := answer + 1;
  Synchronize(ShowResult);
end;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
TMyThread.Create(False);
end;


Скорее всего из-за этого AV было.


> поток даже не запускается!

Как проверил?


Sergey_R   (2005-10-09 14:47:00) [11]

Короче создал я Unit3, где написал:
unit Unit3;

interface

uses
 Classes;

type
 TMyThread = class(TThread) //Новый класс
 private
   answer: Integer;
 protected
   procedure ShowResult;
   procedure Execute; override;
 end;

implementation

uses
 SysUtils, Unit1;

//Процедура для вывода информации из потока
procedure TMyThread.ShowResult;
begin
 Form1.Edit2.Text := IntToStr(answer);
end;

//Длинная процедура
procedure TMyThread.Execute;
var
 i: Integer;
begin
 for i := 1 to 10000 do
 begin
   answer := answer + 1;
   Synchronize(ShowResult);
 end;
end;

end.


На 1 форме создал Button6
procedure TForm1.Button6Click(Sender: TObject);
var
 MyThread: TMyThread;
begin
 MyThread := TMyThread.Create(False);
end;


и Edit2,  куда выводятся данные потока.
Но почему-то ничего не работает (поток даже не запускается!),
а после закрытия формы вылазит ошибка
Exception EAccessViolation in module Project1.exe at 0001A6C8...

Но! Если создать новое приложение,
в Unit2 которого занести поток,
то все работает отлично! Почему так?


GuAV   (2005-10-09 12:48:00) [12]

TUser ©   (05.10.05 11:48) [5]
Synchronize(<метод этого класса, кторый апдейтит ProgressBar>);

Synchronize - IMHO неоправданная роскошь для этого случая. PostMessage вполне хватит.


Sergey_R   (2005-10-09 12:13:00) [13]

А зачем нужен Sleep(0)? Вроде ничего и не произойдет, если его убрать!


TUser   (2005-10-05 11:48:00) [14]

Ну и прекрасно - сделай себе наследника от TThread, напиши ему в методе Execute
while not Terminated do begin
<некоторый повыторяемый код>
Synchronize(<метод этого класса, кторый апдейтит ProgressBar>);
sleep(0);
end;

А на этой формочке, где PB лежит положи кнопочку с надписью Отмена и по ее нажатии делай MyThread.Terminate.

См. также свойство TThread.FreeOnTerminated - может быть полезно


Sergey_R   (2005-10-05 11:44:00) [15]

Мне это нужно не для ускорения поиска, а чтобы пользователь знал, что программа не повисла, а выполняет какие-то действия!


TUser   (2005-10-05 11:19:00) [16]

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


Smithson   (2005-10-05 11:17:00) [17]

Чего получить-то хочется? Ускорить процесс будет сложно, а вот нарисовать индикатор - вполне реально. Причем проще его отрисовывать в том же потоке, что и поиск, после обработки каждого n-го файла (n => 1 ;)). Только перед этим надо подсчитать количество файлов, попадающих под обработку. Тот же поиск, но просто подсчет. Потери времени на этот поиск, в принципе, на системе NTFS даже окупятся, поскольку каталоги закешируются и при отсутсвии интенсивного файлового обмена на машине следующий поиск по этим каталогам пойдет существенно быстрее.


Владислав   (2005-10-05 11:08:00) [18]

Как-нибудь можно вынести в поток. И прогресс показать. Только сканировать быстрее от этого не станет.


Наверх

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