Как мне один раз загрузить изображение и передать его в многопоточном приложении C #? - PullRequest
4 голосов
/ 09 сентября 2011

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

Ход программы идет так: выпредставлены с основной формой, с кнопкой обзора (что вы можете альтернативно перетащить папку на).Когда вы выбираете папку, она открывает другую форму, которая сканирует выбранную папку для изображений .jp [e] g и .tif [f] и представляет их в списке, спрашивая, какую из них вы хотите обрезать, а также некоторые другие.опции.Затем он возвращается к основной форме, которая просматривает список выбранных изображений из этой формы и в пределах BackgroundWorker для каждого загружает его в форму обрезки, затем обрезает и сохраняет его.

Для создания прототипов я немного затрудняю загрузку изображений;он загружает все изображения в папку для формы выбора, затем один за другим загружает каждое выбранное изображение в кадрирующее устройство, а затем еще раз в основной форме для обрезки и сохранения.Для больших изображений это может занять много времени, так как это приложение будет обрабатывать исходные изображения TIFF размером до 4000px 2 в худшем случае.

Я хотел бы подуматьчто есть способ просто загрузить каждый Bitmap один раз в какой-то глобальный массив, но это будет Visual Basic или VB для приложений.Поскольку я использую BackgroundWorker, мне также нужно беспокоиться о безопасности потоков и о том, будет ли C # кричать на меня о попытке доступа к чему-либо небезопасным способом.Любые идеи относительно того, как я могу достичь цели приложения, ограничивая количество загрузок одного изображения в Bitmap объект?

Ответы [ 2 ]

1 голос
/ 09 сентября 2011

Поскольку согласно Microsoft члены экземпляра класса Bitmap не гарантируют поточно-ориентированность, я вижу 2 варианта:

  • производительность, но немного рискованноЗагрузите все как объект Bitmap и добавьте все эти объекты Bitmap к ConcurrentDictionary ... доступ является поточно-ориентированным и очень быстрым, поскольку реализация в основном не блокируется ...

  • чуть менее производительный, но не рискованныйЗагрузите все файлы как MemoryMappedFile в ConcurrentDictionary.когда вам нужно растровое изображение, вы просто создаете MemoryMappedFile (который будет использовать ту же память, уже занятую созданным вами ранее, поэтому очень быстро), и позволяете растровому изображению загружать свой контент оттуда ... когда ваше приложение закрывается или выхочешь убрать, просто пройди по словарю и избавься от этих MemoryMappedFile объектов ...

1 голос
/ 09 сентября 2011

У вас есть два варианта: один объект более ориентирован, чем другой, но сложнее реализовать:

A) Создать некоторый класс (например, Document, BitmapDocument или любой другой), который содержит список, в который вы добавляете всеваши изображения.Не беспокойтесь о многопоточности, просто блокируйте список каждый раз, когда добавляете изображение.В зависимости от того, что вы делаете с растровыми изображениями, вам также может понадобиться заблокировать их.(блокировка не сложна в c #, например, lock (someVariable) {...}) Создание копий растровых изображений (которые уже загружены в список внутри), поскольку их используют различные элементы управления, не должно занимать слишком много памяти / времени (так какбудет оперативной памяти).Сложность возникает, когда основное приложение должно передать этот класс «документа» всем дочерним элементам управления и формам.Как только каждый элемент управления узнает экземпляр «документа», любые дополнения к нему сразу становятся доступными.

B) Создайте некоторый класс, в котором список помечен как внутренний и статический, чтобы любой класс в вашем проекте мог его просматривать и использоватьЭто.Таким образом, вы используете своего рода «глобальный» массив, но не совсем глобальный.Он виден только внутри вашего проекта (из-за «внутреннего» тега) и по-прежнему содержится внутри класса.Обратите внимание, что вам все еще нужно использовать механизм блокировки C #, чтобы сделать все поточно-ориентированным.

Обратите внимание, что вместо прямого доступа к членам класса, вы можете подумать о написании методов для управления ими и соответствующей блокировки объектов.(Это была бы правильная практика программирования.) Для B просто создайте методы, помеченные как «внутренние» и «статические».

Я бы лично использовал B (намного быстрее реализовать и отладить), особенно дляпрототипирование, и, поскольку его использование делает не слишком трудным переход к A в будущем.

Кроме того, если вы используете подход (B) внутренних статических объектов и функций, вы можете написать некоторую функцию, такую ​​какGetBitmap (строковый путь), который загружает изображения с диска, а также содержит буфер всех недавно загруженных изображений, так что потоки не должны загружаться с диска дважды.

...