How to speed up adding images to ImageList?

2.2k views Asked by At

So I'm trying to populate a large amount of icons to a listview. In order to avoid long wait times, I'm trying to get it to load the first 1000 results and then load more if the user presses a load more button.

Here's where I'm stuck. If I load all 10,000+ icons at once it takes me 37 sec. However, if I decide to add 500 more icons everytime the user clicks the button it takes me 40 sec which is worse than adding it all at once! The only difference in code is that I had to make this one line a delegate to avoid cross-threading issues. Is there a faster way to do this?

for (int i = lastLoadedIndex; i < lastLoadedIndex+500; i++)
{
    string file = resultArr[i];

    Invoke((MethodInvoker)delegate()
    {
        this.imageList1.Images.Add(Image.FromFile(file));
    });
}
2

There are 2 answers

3
AnotherDeveloperNamedGreg On

EDIT #2: The expensive part of the function is loading the image from the file. Placing it before locking the mutex should allow for some parallelism worth the overhead of using the mutex. No, this method does not preserve order. EDIT: Add images directly to image list rather than to a temporary collection.

public void LoadImagesFromFiles(string[] files)
{
    Mutex imageListLock = new Mutex();
    files.AsParallel().ForAll(file =>
    {
        var img = Image.FromFile(file);
        imageListLock.WaitOne();
        this.imageList1.Images.Add(img);
        imageListLock.ReleaseMutex();
    });
}
5
Dmitry On

To speed up any bulk operation, consider using the bulk method if it is available.
For instance, the ImageCollection type has the AddRange method.
Try to use it:

int newCount = 500;

// Get a desired part of the `resultArr` array as a new array:
string[] tmp = new string[newCount];
Array.Copy(resultArr, lastLoadedIndex, tmp, 0, newCount);

// Load images:
Image[] images = Array.ConvertAll(tmp, file => Image.FromFile(file));

// Bulk add images to the ImageList:
Invoke((MethodInvoker)(() => imageList1.Images.AddRange(images)));

If won't help, please check which operation is slow: reading of images or appending to the ImageList.