Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.06.07;
Скачать: [xml.tar.bz2];

Вниз

Программа подвисает при запуске цикла   Найти похожие ветки 

 
djkondakov   (2009-04-23 15:34) [0]

Требуется написать программу, которая копирует файлы, пути к которым записаны в TListBox"е, в новое место. Я хотел сделать по старинке, как в Паскале - цикл по записям в списке, а внутри его - цикл по байтам файла. Однако при запуске копирования программа перестает отвечать, и "висит" вплоть до окончания копирования. Пробовал использовать CopyFrom и TTimer, результат тот же. Может, кто знает - как сделать цикл без подвисания программы?


 
Медвежонок Пятачок ©   (2009-04-23 15:38) [1]

она не подвисает.


 
Сергей М. ©   (2009-04-23 15:38) [2]

Вынести логику копирования в доп.код.поток, ибо за интерактив отвечает главный  поток


 
stas ©   (2009-04-23 15:43) [3]

Паралельный поток создавайте.
копировать файлы можно с помощью  функции- Copyfile


 
djkondakov   (2009-04-23 15:51) [4]

А без использования потоков никак нельзя? Просто я еще не очень-то в них...


 
Сергей М. ©   (2009-04-23 15:54) [5]

Можно и без доп.потоков.
Но это лишь уменьшит эффект "зависания", но избавит от него совсем.


 
Anatoly Podgoretsky ©   (2009-04-23 15:59) [6]

Лучшее - shFileOperation

Потоки вообще не нужны при указаном тобой алгоритме, обновлять можно хоть через байт, а ты видимо ни разу.

Код давай.


 
djkondakov   (2009-04-23 16:13) [7]

Угу, принимайте.

procedure TForm1.Button7Click(Sender: TObject);
var stream1, stream2: TFileStream;
   i: integer;
begin
       if edit1.Text<>"" then
               timer1.Enabled:=true
       else showmessage("Не указана папка назначения!");
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var stream1, stream2: TFileStream;
    i: integer;
begin
       if i<=listbox1.Items.Count-1 then begin
               try
                       stream1:=tfilestream.create(listbox2.items[i], fmopenread);
                       stream2:=tfilestream.create(edit1.text+listbox1.items[i], fmcreate);
                       stream2.seek(0,sofromend);
                       stream2.CopyFrom(stream1, stream1.size);
               finally
                       stream1.free;
                       stream2.free;
               end;
               i:=i+1;
       end else begin
       timer1.Enabled:=false;
       showmessage("Копирование завершено");
       end;
end;


Вот. Пояснение - в ListBox1 хранятся имена файлов без пути, а в ListBox2 - полные имена, с путями.


 
Anatoly Podgoretsky ©   (2009-04-23 16:15) [8]

> djkondakov  (23.04.2009 16:13:07)  [7]

Ну и где же тут цикл по байтам?


 
djkondakov   (2009-04-23 16:18) [9]

Цикл по байтам я убрал, когда бился с "зависанием". В итоге ничего не изменилось.


 
Anatoly Podgoretsky ©   (2009-04-23 16:21) [10]

> djkondakov  (23.04.2009 16:18:09)  [9]

Изменилось и еще как - ты сделал "зависание".


 
Медвежонок Пятачок ©   (2009-04-23 16:25) [11]

В итоге ничего не изменилось.

сын: - Папа, почему солнце всегда восходит на востоке, а заходит на западе?
папа-программист: - Это точно?
- Ага!
- Проверял?
- Проверял!!!
- Ничего не трогай, пусть так и работает!


 
djkondakov   (2009-04-23 16:27) [12]

Понятно. Делаю обратно циклы.


 
Anatoly Podgoretsky ©   (2009-04-23 16:42) [13]

> djkondakov  (23.04.2009 16:27:12)  [12]

Не надо делать циклы, по крайней мере по байтам, смотри в сторону shFileOperation или в крайнем случае в сторону CopyFileEx


 
Сергей М. ©   (2009-04-23 16:43) [14]


> Делаю обратно циклы


Не надо ни "обратно" ни вновь)

Можно и без явных циклов обойтись - он уже есть, только неявный.
Все что нужно - сделать свой наследник TFileStream и в нем перекрыть, например,  метод Read.

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


 
Сергей М. ©   (2009-04-23 16:44) [15]


> Anatoly Podgoretsky ©   (23.04.09 16:42) [13]


> CopyFileEx


Она, если не ошибаюсь, такая же блокирующая как и CopyFile


 
djkondakov   (2009-04-23 16:58) [16]

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


 
Медвежонок Пятачок ©   (2009-04-23 17:01) [17]

тяжелый случай .....


 
Anatoly Podgoretsky ©   (2009-04-23 17:02) [18]

> Сергей М.  (23.04.2009 16:44:15)  [15]

Не забывай про функцию обратного вызова, поэтому полублокирующая, точно также как запись кусками с потомщью TFileStream


 
Anatoly Podgoretsky ©   (2009-04-23 17:03) [19]

> Медвежонок Пятачок  (23.04.2009 17:01:17)  [17]

Надежда есть - кусок кода один раз привел.


 
Сергей М. ©   (2009-04-23 17:07) [20]


> Anatoly Podgoretsky ©   (23.04.09 17:02) [18]


Толку-то от колбэка ?

Вызвавший ф-цию код все равно будет "висеть" до фактического окончания копирования..

Да и колбек будет вызываться с частотой, определяемой системой, а не с той с которой было бы желательно для своевременной обработки оконных сообщений


 
Сергей М. ©   (2009-04-23 17:10) [21]


> точно также как запись кусками с потомщью TFileStream


Здесь хотя бы размеры копируемых порций можно контролировать, в отличие от CopyFileEx


 
Ганя   (2009-04-23 17:18) [22]

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


 
djkondakov   (2009-04-23 17:19) [23]

Да, это основная цель программы. Пользователь должен видеть прогресс, ему должно сообщаться, сколько из скольки файлов скопировано.


 
djkondakov   (2009-04-23 17:22) [24]

Индикацию прогресса я как раз сделать не могу, т.к. при копировании у программы не остается времени на отрисовку оконных элементов.


 
Сергей М. ©   (2009-04-23 17:25) [25]


> при копировании у программы не остается времени на отрисовку
> оконных элементов


Так ты сам не даешь ей это время, потому и не отрисовывает)


 
djkondakov   (2009-04-23 17:28) [26]

А как ей, собсно, дать это время? Может, попробовать в цикл sleep запихать?


 
AndreyV ©   (2009-04-23 17:36) [27]

> [26] djkondakov   (23.04.09 17:28)
> А как ей, собсно, дать это время? Может, попробовать в цикл
> sleep запихать?

Ты ответы читал, особенно [4]?


 
Сергей М. ©   (2009-04-23 17:36) [28]

Следует, к примеру, вызвать Application.ProcessMessages.

Сделать это можно в колбэк-функции при использовании CopyFileEx или в теле перекрытого TFileStream.Read (cм. [14])


 
Ганя   (2009-04-23 17:50) [29]


> Да, это основная цель программы. Пользователь должен видеть
> прогресс, ему должно сообщаться, сколько из скольки файлов
> скопировано.

Да, при таком раскладе городить огород с потоками не имеет смысла, присоединяюсь к [28]


 
djkondakov   (2009-04-23 18:08) [30]

Ясно, буду разбираться... Всем спасибо, если что, буду спрашивать здесь.


 
Anatoly Podgoretsky ©   (2009-04-23 18:49) [31]

> Сергей М.  (23.04.2009 17:07:20)  [20]

Толк есть, оно в первую очередь предназначено для организации прогресса, значит обработки событий.


 
Anatoly Podgoretsky ©   (2009-04-23 18:52) [32]


> Да, это основная цель программы. Пользователь должен видеть
> прогресс, ему должно сообщаться, сколько из скольки файлов
> скопировано.

Это вообще другая постановка, между обработкой файлов достаточно времени, что бы показать любого размера видеофайл



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2009.06.07;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.004 c
3-1222155624
ViToTiV
2008-09-23 11:40
2009.06.07
DBExpress. Теряется коннект с MySQL


2-1240244578
Роман
2009-04-20 20:22
2009.06.07
Фильтрация по нескольким полям


15-1238793616
Германн
2009-04-04 01:20
2009.06.07
Копирование документов для отправки их по электронной почте.


15-1238724570
Anatoly Podgoretsky
2009-04-03 06:09
2009.06.07
Сервера Google DataCenter


2-1240556887
Vladislav
2009-04-24 11:08
2009.06.07
Как внести программу в контекстное меню Windows





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский