Текущий архив: 2009.09.27;
Скачать: CL | DM;
Вниз
Чтение/запись файла в отдельном потоке Найти похожие ветки
← →
DevilDevil © (2009-07-22 11:01) [0]Есть ли какие рекомендации? Код?
Как обработать ошибки, отменить, "сделать паузу"?
Какими блоками читать/писать?
← →
Юрий Зотов © (2009-07-22 11:15) [1]Что-то типа этого:
Execute:
while not Terminated do
try
while Pause do // Pause - булевское поле (или свойство) потока
Sleep(1);
Читать (или писать) блок
except
Передать в GUI сообщение об ошибке
Terminate
end;
GUI:
Кнопка "Пауза": Thread.Pause := True;
Кнопка "Продолжить": Thread.Pause := False;
Кнопка "Прервать": Thread.Terminate;
← →
DevilDevil © (2009-07-22 11:21) [2]какой размер блока нужно выставлять? 16кб?
при чтении/записи на CD/флешки/ломаного винта может возникать ошибка. Как её отловить? Ничего не зависнит?
← →
Palladin © (2009-07-22 11:33) [3]
> какой размер блока нужно выставлять? 16кб?
А какая разница в размере блока при использовании основного или дополнительного потока?
> Как её отловить?
А как ты ее в основном отлавливаешь?
> Ничего не зависнит?
А что зависнит? Основной поток виснит?
← →
DevilDevil © (2009-07-22 11:37) [4]> А какая разница в размере блока при использовании основного
> или дополнительного потока?
если не ошибаюсь, чтение/запись файлов происходит по 16кб. Или 32. Или как-то по другому
> А как ты ее в основном отлавливаешь?
Никак
С такими вещами ещё не сталкивался
← →
Palladin © (2009-07-22 11:40) [5]
> [4] DevilDevil © (22.07.09 11:37)
Так ты вообще получается читать/писать не умеешь. С этого и надо начинать.
← →
Юрий Зотов © (2009-07-22 11:46) [6]> DevilDevil © (22.07.09 11:37) [4]
Сначала сделайте пробную программу, где все происходит в одном потоке. Отладьте ее. Затем код чтения/записи вынесите в отдельный поток.
Размер блока может быть любым, Вы должны выбрать его сами (например, один байт - система сама все прокэширует как ей нужно). Он определяется структурой читаемых/записываемых данных, а не потоками.
Отлов ошибок: try-except, либо проверка IOResult (детали - в справке). От потоков это тоже не зависит.
← →
DevilDevil © (2009-07-22 12:12) [7]Использую всегда TFileStream
и не парюсь с IOResult, try/except... или тем более слуачаями, когда тупой юзер вынул сидиром в момент чтения
← →
Sapersky (2009-07-22 13:21) [8]например, один байт - система сама все прокэширует как ей нужно
Насколько помню собственные опыты - плохо она кэширует. Разница между чтением по одному байту и большими фрагментами всегда была заметна. Т.е. при повторном чтении - да, будет и по одному байту быстро (относительно - лишние вызовы функций тоже скорости не добавляют), но кому нужно читать одно и то же несколько раз?
Аналогично с записью.
В D2009, кстати, к TFileStream наконец-то прикрутили буферизацию. Интересно, зачем, если можно читать по одному байту и разницы никакой нет...
Паскалевский TextFile тоже использует буфер.
← →
clickmaker © (2009-07-22 13:27) [9]> [2] DevilDevil © (22.07.09 11:21)
> какой размер блока нужно выставлять? 16кб?
размер блока в идеале должен быть кратен размеру кластера.
Но есть нюансы. Запись по сети, на флэшку и т.д. Разные контроллеры по-разному буферизуют.
При записи на локальный диск лучше брать буфер побольше, н-р 1/5-1/10 размера файла, учитывая количество свободной оперативки. Потому как при недостатке пойдет своп и толку от буфера - ноль.
При записи по сети можно фиксированного размера 2048 или 4096.
При записи на съемный носитель я замечал притормаживание при большом размере буфера.
← →
Anatoly Podgoretsky © (2009-07-22 13:41) [10]
> Sapersky (22.07.09 13:21) [8]
Кеширует она хорошо, потери идут за счет вызова функции, толи вызвать 4096 раз по байту, толи один раз, но 4096 байт. Вызов функции занимает много времени.
В 2009 это перевели на уровень программы, а не ОС, на уровне ОС также кеширование продолжается.
← →
Игорь Шевченко © (2009-07-22 14:01) [11]clickmaker © (22.07.09 13:27) [9]
> размер блока в идеале должен быть кратен размеру кластера.
размеру страницы, раз уж на то пошло.
> При записи на локальный диск лучше брать буфер побольше,
> н-р 1/5-1/10 размера файла, учитывая количество свободной
> оперативки. Потому как при недостатке пойдет своп и толку
> от буфера - ноль.
Товарищ Оракл вывел цифру в 1 мегабайт для единичной операции ввода-вывода. Товарищ проводник, который Explorer, использует буфер в 65536 байт.
> При записи по сети можно фиксированного размера 2048 или
> 4096.
Опять же, товарищ проводник использует 65536 байт.
> При записи на съемный носитель я замечал притормаживание
> при большом размере буфера.
А это зависит исключительно от возможности безопасного извлечения съемного носителя.
← →
clickmaker © (2009-07-22 14:22) [12]> А это зависит исключительно от возможности безопасного извлечения
> съемного носителя.
возможно. Но вот при чтении с сидюка большими блоками я неоднократно замечал тормоза.
← →
Игорь Шевченко © (2009-07-22 14:40) [13]clickmaker © (22.07.09 14:22) [12]
Так может сидюк того, поцарапанный ? :) Я досконально не знаю, как система в этом случае делает retry, только на сбойное место с размером блока CDFS или на размер всей операции ввода-вывода.
← →
DevilDevil © (2009-07-22 15:31) [14]Так по сколько буферизировать: 4кб или 64 ? Или как?
Как отловить ситуацию, если в процессе записи юзер вынимает флешку или диск? Или диск царапан?
← →
clickmaker © (2009-07-22 15:53) [15]> Как отловить ситуацию, если в процессе записи юзер вынимает
> флешку или диск?
try-except или по результату пишущей функции + GetLastError
либо WM_DEVICECHANGE, но это отдельно
← →
DevilDevil © (2009-07-22 16:03) [16]> try-except или по результату пишущей функции + GetLastError
Примерчик бы где посмотреть )
← →
DVM © (2009-07-22 16:05) [17]
> Как отловить ситуацию, если в процессе записи юзер вынимает
> флешку или диск? Или диск царапан?
Операционная система все отловит и оповестит тебя. Анализируй результаты функций WinAPI и будет все ок.
← →
Anatoly Podgoretsky © (2009-07-22 16:24) [18]
> Примерчик бы где посмотреть )
А в [1] это не пример?
← →
clickmaker © (2009-07-22 16:39) [19]> Примерчик бы где посмотреть )
try
...
if not WriteFile(hFile, Data, BytesToWrite, BytesWritten, nil) then
RaiseLastWin32Error();
except
on E: Exception do ShowMessage("юзер вынимает флешку или диск? Или диск царапан? Короче, вот: " + E.Message);
end;
← →
DevilDevil © (2009-07-22 16:42) [20]>clickmaker © (22.07.09 16:39) [19]
Тема
А с FileStream не получится, да?
← →
clickmaker © (2009-07-22 16:48) [21]давно бы уже попробовал...
тоже самое: try-except-finally для закрытия стрима в любом случае
← →
DevilDevil © (2009-07-22 16:59) [22]В Read/Write судя по всему результат будет 0
Тогда можно RaiseLastWin32Error
← →
DevilDevil © (2009-07-24 15:43) [23]Всем спасибо!
Судя по всему - всё получается
Страницы: 1 вся ветка
Текущий архив: 2009.09.27;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.004 c