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

C#静态类成员和System.Windows.Controls.Image性能问题,c#,performance,static-members,C#,Performance,Static Members,我目前正在调查一个应用程序中的性能问题,并强调了以下几点: 我有一节课- public static class CommonIcons { ... public static readonly System.Windows.Media.ImageSource Attributes = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png"); ... } 作为一个

我目前正在调查一个应用程序中的性能问题,并强调了以下几点:

我有一节课-

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
for(int-loop=0;loop<20000;loop++)
{
//通话前储存时间
System.Windows.Controls.Image=新建System.Windows.Controls.Image
{
Source=CommonIcons.Attributes,
宽度=16,
高度=16,
垂直对齐=垂直对齐。中心,
SnapsToDevicePixels=true
};
//通话后存储时间
//记录之前和之后之间的时间
}

在循环开始时,时间差小于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
for(int-loop=0;loop<20000;loop++)
{
//通话前储存时间
System.Windows.Controls.Image=新建System.Windows.Controls.Image
{
Source=typeof(CommonIcons.Assembly.GetImageFromResourcePath(“Resources/attributes.png”),
宽度=16,
高度=16,
垂直对齐=垂直对齐。中心,
SnapsToDevicePixels=true
};
//通话后存储时间
//记录之前和之后之间的时间
}

但是在我的真实程序中,我不想在每次调用时都创建imagesource(在垃圾收集之前增加内存),因此使用静态成员。然而,我也无法忍受这场演出的冲击

有人能解释一下为什么原始代码会产生这种性能冲击吗?还有一个更好的解决方案,我想做什么


谢谢

闻起来像是垃圾收集的味道。我想知道
图像源
图像
之间是否存在某种耦合,这在您的第一个案例中会导致问题。您是否查看了测试线束在每种情况下的内存使用情况


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

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

区别不在于静态成员与否,但在第一个版本中,您创建了20000个图像,所有图像都具有相同的图像源。我不知道到底发生了什么,但在引擎盖下可能会自动创建代理来处理imagesource和image之间的通信,每次imagesource中发生事件时,都需要通知20000个客户端,因此这是一个巨大的性能损失

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


注意您应该始终使用其
dispose()
-方法处理图像等图形对象。处理完这些对象后,这将稍微加快应用程序的速度,并降低一般内存使用率。

只是出于兴趣,如果您在发布模式下运行代码或打开优化,使用静态版本会发生什么?在发布模式下运行会显示同样的情况。发布可以在我们的机器上运行的代码。至少缺少扩展方法。我已经更新了上面的名称空间,这足以让您运行吗?对于第一种情况,内存使用增加。在结束时强制垃圾收集不会释放内存。对于第二种情况,内存使用量增加得更多,但在最后强制执行垃圾回收会释放内存备份。我在测试工具中采纳了您的建议,并在每次迭代结束时将源代码设置为null,这样就可以在不再影响性能的情况下工作。为什么会这样?谢谢:)@TheBlackKnight:嗯,大概
ImageSource
以某种方式创建了一个
图像列表。这可以防止图像被垃圾收集,所以在第一种情况下,GC压力是恒定的。解决方法:不要这样做:)在处理完图像后清除图像源。谢谢你的回答。System.Windows.Controls.Image没有dispose方法(System.Drawing.Image有)。