![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обработка файлов в потоке [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]Как-нибудь можно вынести в поток. И прогресс показать. Только сканировать быстрее от этого не станет.