Ускорьте загрузку изображения с диска в приложении Windows Forms (C # .NET) - PullRequest
8 голосов
/ 29 июля 2009

В настоящее время я работаю над приложением, которое позволяет пользователю воспроизводить (автоматически прокручивать) серию локальных изображений. Обычно на экране сразу пять или шесть человек.

Основным узким местом на данный момент является фактическая загрузка данных изображения с диска. Поток таймера требует, чтобы изображения обновлялись каждые 1/6 секунды, и приложение изо всех сил пытается не отставать от этой скорости. Каждое изображение составляет около 25 КБ.

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

Каждый такт таймера, я зацикливаюсь на шести заполнителях изображений, загружая следующее изображение, используя стандартный

Image img = Image.FromFile("filename");

метод, но подумал, что кто-то может знать о более быстром способе извлечения образов с диска.

В каждом из шести комплектов содержится от 500 до 20000 изображений, поэтому он слишком велик, чтобы загрузить все это в память при запуске.

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


Отредактируйте, чтобы добавить более подробную информацию о потоке приложений.

Хорошо, вот что происходит:

Пользователь нажимает кнопку воспроизведения. Поток таймера начинается с тайм-аута 1/6 секунды.

Таймер обратного вызова:

Update image index (_index++)
for each viewer in list of visible viewers (the forms to display images)
{
    get the filename from the id stored in the viewer
    check to see if the file exists
    if it does exist,
        create new bitmap from image
        and return that image
    otherwise return null

    if returned image isn't null, display it on screen
}

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

Ответы [ 6 ]

9 голосов
/ 29 июля 2009

Я встречал эту страницу , которая описывает, как использовать GDI + API напрямую для загрузки изображений. Очень прост в использовании:

ImageFast.FromFile(@"C:\MyPhoto.JPG");

Добавлено для отображения скорости ImageFast по сравнению с методом Image From File

Здесь используется найденный исходный код здесь . Код был скопирован и вставлен и не требует изменений.

Stopwatch watch = Stopwatch.StartNew();

string filePath = @"C:\TestImage25k.png";

Image fromFile = Image.FromFile(filePath);

watch.Stop();

Console.WriteLine("Image.FromFile     Ticks = {0:n}", watch.ElapsedTicks);

long fromFileTicks = watch.ElapsedTicks;

watch.Reset();
watch.Start();

Image fastImage = ImageFast.FromFile(filePath);

watch.Stop();

long fastFileTicks = watch.ElapsedTicks;

Console.WriteLine("ImageFast.FromFile Ticks = {0:n}", watch.ElapsedTicks);

Console.WriteLine("fromFileTicks - fastFileTicks = {0:n}", fromFileTicks - fastFileTicks);

Вывод на консоль был

Image.FromFile     Ticks = 19,281,605.00

ImageFast.FromFile Ticks = 7,557,403.00

fromFileTicks - fastFileTicks = 11,724,202.00

Вы можете увидеть влияние ImageFast. Со временем эти 11 миллионов сохраненных тиков будут складываться.

1 голос
/ 12 декабря 2009

Думаю, концепция двойной буферизации будет полезна. Установите для свойства «Двойной буфер» формы значение True. Это поможет вам немного. Следующие ссылки могут быть полезны для вас

1 голос
/ 29 июля 2009

Ознакомьтесь с концепцией двойной буферизации . То, что вы хотите сделать, это иметь второй поток, который может загружать следующий набор изображений , в то время как вы отображаете первый набор. По достижении 1/6 времени вы выключаете один набор изображений и начинаете загружать следующий набор.

1 голос
/ 29 июля 2009

Проще всего поставить кнопку «следующий» и «предыдущий», чтобы ограничить количество изображений и предварительную загрузку.

0 голосов
/ 29 июля 2009

Я бы, вероятно, создал фоновый поток, чтобы непрерывно извлекать все изображения с диска (поддерживает отзывчивость интерфейса), а затем публиковать каждое вновь загруженное изображение через событие

0 голосов
/ 29 июля 2009

Если у вас отображается 6 изображений одновременно и вы меняете их каждые 1/6 секунды, у вас могут возникнуть проблемы с производительностью. Загрузка 150 КБ с диска должна быть тривиальной задачей даже без кэширования. Похоже, вы переусердствовали с загрузкой файлов. Вы уверены, что загружаете только 6 изображений одновременно? Вы читаете изображения с диска, которые не отображаются?

Если вы можете немного подробнее рассказать о процессе подачи заявки, возможно, я смогу быть немного более полезным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...