Как ускорить добавление изображений в ImageList?

Поэтому я пытаюсь заполнить большое количество значков в виде списка. Чтобы избежать длительного времени ожидания, я пытаюсь заставить его загрузить первые 1000 результатов, а затем загрузить больше, если пользователь нажимает кнопку "загрузить больше".

Вот где я застрял. Если я загружаю все 10 000+ иконок одновременно, это занимает 37 секунд. Однако, если я решу добавить еще 500 значков каждый раз, когда пользователь нажимает кнопку, у меня уходит 40 секунд, что хуже, чем добавлять все сразу! Единственная разница в коде заключается в том, что мне пришлось сделать эту строку делегатом, чтобы избежать проблем с многопоточностью. Есть ли более быстрый способ сделать это?

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

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

2 ответа

Чтобы ускорить любую массовую операцию, рассмотрите возможность использования массового метода, если он доступен.
Например, ImageCollection тип имеет AddRange метод.
Попробуйте использовать это:

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)));

Если это не поможет, проверьте, какая операция выполняется медленно: чтение изображений или добавление к ImageList,

РЕДАКТИРОВАТЬ #2: дорогая часть функции загружает изображение из файла. Размещение его перед блокировкой мьютекса должно обеспечить некоторый параллелизм, который стоит затрат на использование мьютекса. Нет, этот метод не сохраняет порядок. РЕДАКТИРОВАТЬ: Добавить изображения непосредственно в список изображений, а не во временную коллекцию.

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();
    });
}
Другие вопросы по тегам