C#静态类成员和System.Windows.Controls.Image性能问题

时间:2010-09-23 10:42:15

标签: c# performance static-members

我目前正在调查应用程序中的性能问题,并强调了以下内容;

我有一个班级 -

public static class CommonIcons
{
    ...
    public static readonly System.Windows.Media.ImageSource Attributes = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png");
    ...
}

作为测试工具,我使用此类使用以下代码来显示问题 -

for (int loop = 0; loop < 20000; loop++)
{
    // store time before call

    System.Windows.Controls.Image image = new System.Windows.Controls.Image
                    {
                        Source = CommonIcons.Attributes,
                        Width = 16,
                        Height = 16,
                        VerticalAlignment = VerticalAlignment.Center,
                        SnapsToDevicePixels = true
                    };

    // store time after call
    // log time between before and after

}

在循环开始时,时差小于0.001秒,但在20000之后,这已经增加到0.015秒。

如果我不使用静态成员并直接参考我的图标,那么我没有性能损失,即

for (int loop = 0; loop < 20000; loop++)
{
    // store time before call

    System.Windows.Controls.Image image = new System.Windows.Controls.Image
                    {
                        Source = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png"),
                        Width = 16,
                        Height = 16,
                        VerticalAlignment = VerticalAlignment.Center,
                        SnapsToDevicePixels = true
                    };

    // store time after call
    // log time between before and after

}

但在我的真实世界程序中,我不想在每次调用时创建imagesource(增加内存直到垃圾收集),因此使用静态成员的原因。但是我也无法忍受性能打击。

有人可以解释为什么原始代码会产生这种性能影响吗?还有一个更好的解决方案,我正在尝试做什么?

由于

3 个答案:

答案 0 :(得分:1)

它闻起来与垃圾收集有关。我想知道ImageSourceImage之间是否存在某种耦合,这会导致第一种情况出现问题。您是否想过了解每种情况下测试工具的内存使用情况?

出于兴趣,如果在每次迭代结束时将Source设置为null会发生什么?我知道这有点傻,但那是它作为测试工具的一个自然结果:)它可能进一步表明它是源和图像之间的链接......

答案 1 :(得分:0)

你能在CommonIcons类中只存储像“Resources / attributes.png”这样的常量字符串吗?

答案 2 :(得分:0)

区别在于静态成员与否之间,但在第一个版本中,您创建的20000个图像都具有相同的图像源。我不确切知道发生了什么,但是在幕后可能会有自动创建的委托来处理imagesource和image之间的通信,每次如果在imagesource中发生事件,就需要通知20000个客户端,所以这是一个很大的表现很受欢迎。

在第二个版本中,20000个创建的图像中的每一个都有自己的图像源,因此您不会遇到这种开销。

注意您应该在完成后使用Dispose() - 方法处理图像等图形对象,这样可以加快应用程序的速度并降低一般内存使用量