Re: Directory enumerate files async
От: pilgrim_ Россия  
Дата: 13.11.24 11:39
Оценка: +4
Здравствуйте, HotDog, Вы писали:

HD>Сейчас используем обычный Directory.GetFiles, который долго тупит на таком количестве файлов.

..
HD>Может кто-то видел подобное решение?

Directory.EnumerateFiles ? По мере получения файлов можно складывать в спец. очередь, которую можно обрабатывать параллельно по мере поступления файлов.
Re: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 14:25
Оценка: 6 (1)
Здравствуйте, HotDog, Вы писали:

HD>Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках.

HD>Нужно показывать содержимое этих директориев.

Я бы немного с другой стороны подошел бы.

Где показывать ? Сколько в окне показывать (не миллион же!). И как показывать — последовательно или в произвольном порядке, то есть с произвольным скроллингом ?

Если последовательно, то можно использовать для ListView или DataGridView виртуальный режим.

Начинаешь Directory.EnumerateFiles в отдельном потоке, заносишь данные в какой-то ArrayList с большой начальной емкостью (чтобы избежать насколько можно переаллокаций) и сразу же показываешь то, что поместилось в окне. Пока пользователь листает вперед, ArrayList дозаполняется.

Увы, если надо показывать в произвольном порядке, это не пройдет — там лишь IEnumerable.
With best regards
Pavel Dvorkin
Re: Directory enumerate files async
От: m2user  
Дата: 13.11.24 12:09
Оценка: +1
HD>Может кто-то видел подобное решение?

Если нужно чтобы каждый вызов был асинхронным, то смотри NtQueryDirectoryFile.
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntquerydirectoryfile#remarks

The NtQueryDirectoryFile routine returns information about files that are contained in the directory represented by FileHandle.

Её можно вызывать из C# через pinvoke. А также она поддерживает асинхронный вызов в отличие от FindNextFile.

Если же тебе достаточно синхронной постраничности, то про DirectoryInfo.EnumerateFileSystemInfos уже писали выше.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 12:15
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А, я-то подумал, что GetFiles вызывается регулярно, чтобы отслеживать появление новых файлов в каталоге. Если надо только один раз, то EnumerateFiles должно сгодиться.


Ну такие действия при миллионах файлов я бы вообще отказался делать

Но вообще-то EnumerateFiles это скорее всего настройка над FindFirstFile-FileNextFile. От GetFiles это будет отличаться тем, что не будет создан жуткого размера массив string[]. Все в одну переменную, как в FindFirstFile-FileNextFile. По крайней мере я на это надеюсь.

А вот в ядре асинхронно не будет. Это, если я правильно понимаю, можно только через NtQueryDirectoryFile c APC. Впрочем, тебе тут лучше знать
With best regards
Pavel Dvorkin
Re[9]: Directory enumerate files async
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.11.24 14:17
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>ТС нужно именно весь.


ТС спрашивал, можно ли это делать асинхронно (скорее всего, чтоб крутить индикатор ожидания). Он не просил чуда.
Re[8]: Directory enumerate files async
От: m2user  
Дата: 13.11.24 15:54
Оценка: +1
ЕМ>Десятки секунд занимает обход всего каталога. А отдельная операция типа FindNextFile выполняется быстро.

Это весьма сильное допущение. Устройство, на котором расположена ФС, может вести себя непредсказуемо.
Это может быть сетевой диск (SMB), iSCSI, WebDAV на канале с неизвестной пропускной способностью.

И подвисший UI, либо утекшие ресурсы из-за криво сделанного cancellation потом о себе дадут знать.
Directory enumerate files async
От: HotDog Швейцария www.denebspace.com
Дата: 13.11.24 11:32
Оценка:
Всем привет!
Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках.
Нужно показывать содержимое этих директориев.
Сейчас используем обычный Directory.GetFiles, который долго тупит на таком количестве файлов.
Наверняка мы не первые кто сталкивается с такой проблемой, но я по-быстрому не мог нагуглить решение.
В идеальном виде хотелось бы иметь что-то типа

ObservableCollection<string> files = Directory.GetFilesAsync()


Может кто-то видел подобное решение?
Re: Directory enumerate files async
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.11.24 11:43
Оценка:
Здравствуйте, HotDog, Вы писали:

HD>Сейчас используем обычный Directory.GetFiles, который долго тупит на таком количестве файлов.


В нативном WinAPI есть ReadDirectoryChanges. Если нечто подобное есть в POSIX, то и в .NET, скорее всего, как-то отражено.
Re[2]: Directory enumerate files async
От: pilgrim_ Россия  
Дата: 13.11.24 11:48
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В нативном WinAPI есть ReadDirectoryChanges. Если нечто подобное есть в POSIX, то и в .NET, скорее всего, как-то отражено.


Да, есть — FileSystemWatcher (в win под капотом ReadDirectoryChanges).
Отредактировано 13.11.2024 11:50 pilgrim_ . Предыдущая версия .
Re[2]: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 12:04
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В нативном WinAPI есть ReadDirectoryChanges. Если нечто подобное есть в POSIX, то и в .NET, скорее всего, как-то отражено.


Это немного не то. Это изменения в каталоге

А нужно FindFirstFile — FindNextFile

Или на .NET Directory.EnumerateFiles, как уже было отмечено.
With best regards
Pavel Dvorkin
Re[3]: Directory enumerate files async
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.11.24 12:07
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А нужно FindFirstFile — FindNextFile


А, я-то подумал, что GetFiles вызывается регулярно, чтобы отслеживать появление новых файлов в каталоге. Если надо только один раз, то EnumerateFiles должно сгодиться.
Re[5]: Directory enumerate files async
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.11.24 13:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>в ядре асинхронно не будет.


А надо? FindFileNext даже для миллионов файлов будет работать доли секунды.
Re[6]: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 13:39
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А надо? FindFileNext даже для миллионов файлов будет работать доли секунды.


Ох, не знаю. Миллионов файлов у меня не было, а вот примерно 100 тысяч в одном каталоге было, правда, лет 20 назад. И когда в FAR я входил в этот каталог, занимало это десятки секунд.
Конечно, не SDD, а HDD, да и 20 лет назад все же. Но те же 7200RPM.
With best regards
Pavel Dvorkin
Re[7]: Directory enumerate files async
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.11.24 13:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>занимало это десятки секунд.


Десятки секунд занимает обход всего каталога. А отдельная операция типа FindNextFile выполняется быстро.
Re[8]: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 14:12
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Десятки секунд занимает обход всего каталога. А отдельная операция типа FindNextFile выполняется быстро.


Да, но ТС нужно именно весь. Да еще и не один каталог.

TC>Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках.

TC>Нужно показывать содержимое этих директориев.
With best regards
Pavel Dvorkin
Re[10]: Directory enumerate files async
От: Pavel Dvorkin Россия  
Дата: 13.11.24 14:27
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>ТС спрашивал, можно ли это делать асинхронно (скорее всего, чтоб крутить индикатор ожидания). Он не просил чуда.


Угу. Хоть и не асинхронно, но

https://rsdn.org/forum/dotnet/8851885.1
Автор: Pavel Dvorkin
Дата: 13.11 17:25
With best regards
Pavel Dvorkin
Directory enumerate files async
От: HotDog Швейцария www.denebspace.com
Дата: 14.11.24 14:54
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Где показывать ? Сколько в окне показывать (не миллион же!). И как показывать — последовательно или в произвольном порядке, то есть с произвольным скроллингом ?


По сути, у меня что то вроде эксплорера. Есть дерево каталогов (директориев) и пользователь просто клацает по директориям и хочет посмотреть что в них лежит. Понятно, что я не показываю все миллионы файлов за раз, но нужна быстрая реакция при выборе директория и возможность прервать загрузку. А сейчас это выглядит так — пользователь кликает на директорий и приложение "задумывается" на очень долго, т.к пока Directory.GetFiles все не вычитает, нам показывать нечего

PD>Начинаешь Directory.EnumerateFiles в отдельном потоке, заносишь данные в какой-то ArrayList с большой начальной емкостью (чтобы избежать насколько можно переаллокаций) и сразу же показываешь то, что поместилось в окне. Пока пользователь листает вперед, ArrayList дозаполняется.

PD>Увы, если надо показывать в произвольном порядке, это не пройдет — там лишь IEnumerable.

Сейчас взял IAsyncEnumerable и вот отсюда код, как идею https://github.com/dotnet/runtime/issues/809
Отредактировано 14.11.2024 16:01 HotDog . Предыдущая версия .
Re[3]: Военком отвечает на вопросы
От: Pavel Dvorkin Россия  
Дата: 14.11.24 15:05
Оценка:
Здравствуйте, HotDog, Вы писали:

HD>Сейчас взял IAsyncEnumerable и вот отсюда код, как идею https://github.com/dotnet/runtime/issues/809


Да, примерно то, что тут говорили. В отдельном потоке.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.