加速在Windows窗体(c#.net)应用程序中从磁盘加载图像

我目前正在开发一款应用程序,允许用户播放(自动滚动)一系列本地图像。 通常屏幕上会同时有五个或六个。

目前的主要瓶颈似乎是从磁盘实际加载图像数据。 计时器线程要求每1/6秒更新一次图像,应用程序正在努力跟上这个速度。 每张图片大约25Kb。

我尝试创建一个滚动缓存来尝试和预加载图像,但这也被赶上了自己,所以最终放慢了同样的速度。

计时器的每一个节拍,我循环使用标准加载下一个图像的六个图像占位符

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

方法,但认为有人可能知道更快的方式从磁盘上获取图像。

在六组中的每一组中都有500到20,000个图像,所以它太大而无法在开始时将整个内容加载到内存中。

如果有人建议以更快的方式拉动这些图像,那将非常感激。


编辑以添加应用程序流的更多细节。

好的,这就是发生的事情:

用户点击“播放”按钮。 定时器线程以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 } 

这显然是跨越几个层次 – 图像加载在服务层中继续,然后将其传递到演示文稿,然后传递到UI,但这是正在发生的事情的要点。

我遇到了这个页面 ,它描述了如何直接使用GDI + API来加载图像。 使用非常简单:

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

添加以显示ImageFast over 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的影响。 随着时间的推移,这1100万个节省的蜱将加起来。

最简单的可能是放置“下一个”和“上一个”按钮来限制图像数量和预加载。

看看双缓冲的概念。 你想要做的是有第二个线程,可以在显示第一组加载下一组图像。 一旦1/6时间门命中,您将一组图像切换出来并开始加载下一组图像。

如果您同时显示6个图像,并且每1/6秒更改一次,则应该遇到性能问题。 即使没有缓存,从磁盘加载150 kb应该是一项微不足道的活动。 听起来你可能会过度负载文件。 您确定一次只能加载6张图片吗? 您是否从磁盘读取未显示的图像?

如果您能提供更多应用程序流程的详细信息,我可能会更有帮助。

我可能会创建一个后台线程来连续从磁盘获取所有图像(保持ui响应),然后通过事件发布每个新加载的图像

我认为双缓冲的概念将是有用的。 将窗体的“Double Buffer”属性设置为True。 这对你有所帮助。 以下链接可能对您有用