【问题标题】:Speed up loading an image from disk in a windows forms (c#.net) app加快在 Windows 窗体(c#.net)应用程序中从磁盘加载图像
【发布时间】:2009-07-29 15:48:36
【问题描述】:

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

目前的主要瓶颈似乎是从磁盘实际加载图像数据。计时器线程要求图像每 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,但这就是正在发生的事情的要点。

【问题讨论】:

    标签: c# winforms image


    【解决方案1】:

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

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

    添加以显示 ImageFast over Image From File 方法的速度

    这使用找到的源代码here。代码已复制粘贴,无需更改。

    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 刻度 = 19,281,605.00 ImageFast.FromFile 刻度 = 7,557,403.00 fromFileTicks - fastFileTicks = 11,724,202.00

    您可以看到 ImageFast 的影响。随着时间的推移,这 1100 万个保存的刻度将加起来。

    【讨论】:

    • 我写了一个快速测试应用来测试这个,ImageFast 快了 1100 万个滴答声。 Image 的 from 文件需要 1900 万,而 ImageFast 只需要 700 万。
    • 感谢测试结果,大卫 :)
    • 没问题。我喜欢 ImageFast 的结果。
    • 非常感谢,我已经更新了加载机制以使用它从磁盘读取。我可能会将它与双缓冲一起使用,看看我能以多快的速度运行它。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      查看double buffering 的概念。您想要做的是有第二个线程,可以在您显示第一组图像的同时加载下一组图像。一旦 1/6 时间门命中,您切换一组图像并开始加载下一组。

      【讨论】:

        【解决方案4】:

        我认为双缓冲的概念会很有用。将表单的“双缓冲区”属性设置为 True。这将对您有所帮助。以下链接可能对您有用

        【讨论】:

          【解决方案5】:

          如果您一次显示 6 张图像,并且每 1/6 秒更改一次,那么您应该会遇到性能问题。即使没有缓存,从磁盘加载 150 kb 也应该是一件小事。听起来您可能过度加载文件。您确定一次只加载 6 张图片吗?您是否正在从磁盘读取未显示的图像?

          如果你能提供更多关于申请流程的细节,我可能会更有帮助。

          【讨论】:

          • 嗨,我已经编辑了问题以显示一些应用流程。它肯定一次只加载 6 张图像。如果我开始关闭一些“查看器”窗口,它会明显加速。我还尝试在播放前将每组中的前 50 张图像读取到内存中,这完全消除了瓶颈,所以似乎只是加载会减慢速度。
          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-07
            • 2017-07-28
            • 1970-01-01
            相关资源
            最近更新 更多