I’m writing an app whose purpose is to find images within a folder and present them to the user asking how they should be cropped. With all of the jumping I do from language to language on a daily basis, I tend to get my best practices and concepts jumbled up, and this is such a case.
Program flow goes like this: you’re presented with the main form, with a browse button (that you could alternatively drop a folder onto). When you select a folder, it opens another form that scans the selected folder for .jp[e]g and .tif[f] images and presents them in a list, asking which of them you’d like to crop, and some other options. Then it goes back to the main form which goes through the list of selected images from that form, and within a BackgroundWorker for each one it loads it into a cropping form, then crops it and saves it.
For prototyping I handle the loading of images a bit messily; it loads all the images in the folder for the selection form, then it loads each selected image again in the cropper one-by-one, and then one more time in the main form to be cropped and saved. For large images, this could make the task time-consuming, as this app would handle TIFF source images up to about 4000px2 in a worst-case scenario.
I would like to think that there is a way to just load each Bitmap once into some sort of global array, but that would be Visual Basic or VB for Applications. Since I’m using a BackgroundWorker I also have to worry about thread safety and whether or not C# will yell at me about trying to access something in an unsafe manner. Any ideas as to how I can accomplish the app’s purpose while limiting the number of times a single image is loaded into a Bitmap object?
Since according to Microsoft the Bitmap class instance members are not guaranteed to be thread-safe I see 2 options:
performant but a bit risky
Load everything as a Bitmap object and add all those Bitmap objects to a
ConcurrentDictionary… the access is thread-safe and very fast since the implementation is mostly lock-free…a bit less performant but not risky
Load all files as
MemoryMappedFileinto aConcurrentDictionary. when you need a Bitmap you just create aMemoryMappedFile(which will use the same memory already occuppied by the onece you created before thus extremely fast) and let the Bitmap load its content from there… when your app shuts down or you want to cleanup you just go through the Dictionary and get rid of thoseMemoryMappedFileobjects…