Как быстро обработать множество файлов в приложении C # для настольных ПК без зависания приложения - PullRequest
0 голосов
/ 18 мая 2019

У меня есть около 500 изображений JPEG на съемном носителе. Мое настольное приложение (.NET 4.5) представляет собой одну форму Winforms, которая в настоящее время содержит объекты FileInfo для этих изображений в списке с помощью Directory.EnumerateFiles. Нет проблем там и очень быстро. Основная цель состоит в том, чтобы взять все эти файлы и загрузить их в корзину S3, одновременно выполняя небольшую запись в журнал с помощью вызова REST API и сообщая пользователю о ходе выполнения всех файлов, и, конечно же, когда весь набор файлов готов. загрузка.

Как я могу взять этот список объектов FileInfo и обработать их наиболее эффективно, одновременно обновляя индикатор выполнения и позволяя пользователю перемещать форму без ее зависания? Делать вещи в простом цикле ForEach очевидно медленно. Обработка каждого файла включает в себя загрузку изображения в корзину S3, если существуют определенные поля метаданных, запись в REST API для сохранения записи в базе данных SQL, затем обновление пользовательского интерфейса для уведомления пользователя о прогрессе, а также пометка файла в визуальном элементе. Сетка данных как "сделано". Я могу делать весь этот код нормально, но не знаю, как пройти этот список файлов одновременно, не вызывая проблем с пользовательским интерфейсом в форме.

Мой реальный вопрос: я слышал, что многие упоминали Parallel.ForEach, TPL, используя Tasks, Async / Await, и я пытаюсь понять, какой вариант является лучшим для моего варианта использования, и как это сделать для обновления Пользовательский интерфейс / прогрессбар без проблем.

1 Ответ

2 голосов
/ 18 мая 2019

Поскольку это рабочая нагрузка, связанная с IO , и ваши библиотеки, вероятно, поддерживают async, тогда можно использовать шаблон асинхронности и ожидания .Это позволит эффективно использовать потоков пула потоков , в то время как OS имеет дело с портами завершения ввода-вывода , что означает, что в то время, когда работа выгружается в операции, связанные с вводом-выводом, пул потоков может повторно использоватьэтот ценный ресурс, в то время как Pattern также управляет продолжениями и контекстом синхронизации , так что вы можете обновить UI

, так какParallel.For/ForEach не поддерживает шаблон асинхронного ожидания и будет в конечном счете неэффективным, простейшим путем будет использование Task.Run и Task.WhenAll с async методами.

Тем не менее, я бы также взглянул на ActionBlock<T> в библиотеке Microsoft TPL DataFlow Это даст вам лучшее из того, что вы можете использовать async иожидайте паттерна , а также ограничивайте максимальные степени параллелизма.

Другим вариантом будет реактивных расширений , который также имеет все эти лакомства

...