C# 画笔。白色会减慢图形演示的速度

C# 画笔。白色会减慢图形演示的速度,c#,wpf,conways-game-of-life,brushes,C#,Wpf,Conways Game Of Life,Brushes,下面是康威在WPF中的生活游戏的一个(非常幼稚的)实现。这只是一个演示 xaml: 代码隐藏: using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Threading; namespace wpf_conway_life_2013_05_19 {

下面是康威在WPF中的生活游戏的一个(非常幼稚的)实现。这只是一个演示

xaml:


代码隐藏:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace wpf_conway_life_2013_05_19
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var random = new Random();

            var data = new int[100, 100];

            var dataB = new int[100, 100];

            Func<int, int, int> at = (x, y) =>
                {
                    if (x < 0) x = 100 + x;
                    if (x >= 100) x = x % 100;
                    if (y < 0) y = 100 + y;
                    if (y >= 100) y = y % 100;

                    return data[x, y];
                };

            for (var x = 0; x < 100; x++)
                for (var y = 0; y < 100; y++)
                    data[x, y] = random.Next(2);

            var rectangles = new Rectangle[100, 100];

            for (var x = 0; x < 100; x++)
                for (var y = 0; y < 100; y++)
                {
                    rectangles[x, y] = new Rectangle();

                    canvas.Children.Add(rectangles[x, y]);
                }

            canvas.SizeChanged += (s, e) =>
                {
                    for (var x = 0; x < 100; x++)
                    {
                        for (var y = 0; y < 100; y++)
                        {
                            rectangles[x, y].Width = canvas.ActualWidth / 100;
                            rectangles[x, y].Height = canvas.ActualHeight / 100;

                            Canvas.SetLeft(rectangles[x, y], (canvas.ActualWidth / 100) * x);
                            Canvas.SetTop(rectangles[x, y], (canvas.ActualHeight / 100) * y);
                        }
                    }
                };

            Action macroStep = () =>
                {
                    dataB = new int[100, 100];

                    for (var x = 0; x < 100; x++)
                    {
                        for (var y = 0; y < 100; y++)
                        {
                            var neighbors = 0;

                            for (var i = -1; i <= 1; i++)
                                for (var j = -1; j <= 1; j++)
                                    if (i == 0 && j == 0)
                                        continue;
                                    else
                                        neighbors += at(x + i, y + j);

                            dataB[x, y] = data[x, y];

                            if (neighbors < 2) dataB[x, y] = 0;
                            if (neighbors == 3) dataB[x, y] = 1;
                            if (neighbors > 3) dataB[x, y] = 0;

                            rectangles[x, y].Fill = dataB[x, y] == 0 ? new SolidColorBrush(new Color()) : Brushes.Black;
                        }
                    }

                    data = dataB;
                };

            var timer = new DispatcherTimer();

            timer.Tick += (s, e) => macroStep();

            timer.Start();
        }
    }
}
使用系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Media;
使用System.Windows.Shapes;
使用System.Windows.Threading;
名称空间wpf_conway_life_2013_05_19
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
var random=新的random();
var数据=新整数[100100];
var DATB=新整数[100100];
Func at=(x,y)=>
{
如果(x<0)x=100+x;
如果(x>=100)x=x%100;
如果(y<0)y=100+y;
如果(y>=100)y=y%100;
返回数据[x,y];
};
对于(变量x=0;x<100;x++)
对于(变量y=0;y<100;y++)
数据[x,y]=随机。下一步(2);
变量矩形=新矩形[100100];
对于(变量x=0;x<100;x++)
对于(变量y=0;y<100;y++)
{
矩形[x,y]=新矩形();
canvas.Children.Add(矩形[x,y]);
}
canvas.SizeChanged+=(s,e)=>
{
对于(变量x=0;x<100;x++)
{
对于(变量y=0;y<100;y++)
{
矩形[x,y].Width=canvas.ActualWidth/100;
矩形[x,y]。高度=画布。实际高度/100;
Canvas.SetLeft(矩形[x,y],(Canvas.ActualWidth/100)*x);
Canvas.SetTop(矩形[x,y],(Canvas.ActualHeight/100)*y);
}
}
};
动作宏步骤=()=>
{
数据=新整数[100100];
对于(变量x=0;x<100;x++)
{
对于(变量y=0;y<100;y++)
{
var=0;
对于(var i=-1;i macroStep();
timer.Start();
}
}
}
下面是它的样子:

如果我将
new SolidColorBrush(new Color())
替换为
brush.White
程序运行速度会慢得多。为什么


我正在使用2010 Express在Windows 7 64位上进行测试。

因为
新颜色()
的alpha值为零,这意味着WPF不必渲染它,因为它是完全透明的-另一方面,白色的alpha值是255,这意味着它是必须渲染的完全纯白颜色。

使用
笔刷没有什么特别的。白色

如果在macroStep事件处理程序外定义自己的本地笔刷,然后将其冻结,则其行为将与使用brush.White完全相同。如果不先冻结,其行为将非常糟糕

最好的性能是在每次调用宏步开始时,在循环之前创建一次笔刷,然后将其冻结。如果在最内部的循环中创建一个新笔刷,则会大大降低速度

另外,如果你增加行为不好的代码的计时器间隔,它实际上会解决性能问题。我猜在后台线程每次完成渲染后都会出现某种资源清理,这与画笔的内部结构有关,但它无法进行清理nup,因为您将在下一次迭代中右转并使用笔刷。为了演示这一点,我创建了一个笔刷池,每次使用不同的笔刷:

SolidColorBrush[] brushes = new SolidColorBrush[2];
for (int i = 0; i < brushes.Length; i++)
{
    var brush = new SolidColorBrush(new Color());
    brush.Freeze();
    brushes[i] = brush;
}
int brushIx = 0;

Action macroStep = () =>
{
    dataB = new int[100, 100];
    var brush = brushes[brushIx++ % brushes.Length];
...
    rectangles[x, y].Fill = dataB[x, y] == 0
        ? brush
        : Brushes.Black;
    data = dataB;
};
SolidColorBrush[]画笔=新的SolidColorBrush[2];
对于(int i=0;i
{
数据=新整数[100100];
var brush=画笔[brushIx++%画笔.长度];
...
矩形[x,y]。填充=数据[x,y]==0
?刷子
:黑色;
数据=数据;
};

如果将画笔数设置为1,这将提供与使用
画笔.White
相同的行为。但是如果将其设置为2或更多,您将获得预期的性能。

如果将画笔的缓存引用保留在循环之外并使用该引用代替,则可以缩小渲染或检索问题的范围de>画笔。白色,速度是否受到影响?系统画笔缓存在
字典
中,每次检索项目时都必须锁定该字典。您是否获得与
画笔相同的行为。透明
?@SimonMcKenzie很好的建议。但是,我尝试了它,没有任何区别。(顺便说一句,祝贺MapSnap;非常酷的WP7应用!)谢谢!你必须试一试;)虽然我不知道WPF是否会并行一些渲染,但如果所有项目共享同一个笔刷,则可能会影响渲染。如果在循环外部创建新笔刷实例,性能是否相同?@Rachel
brush。Transparent
也很慢。有趣的是,它一开始并不像
brush.Whit那么慢e
但是经过大约5次迭代后,速度会慢很多。好建议Jaska。但是如果是这样,那么速度也会一样慢:
new SolidColorBrush(new Color(){R=255,G=255,B=255,A=255})
。但事实并非如此。感谢布莱斯的建议。您是否在您的系统上测试了此代码,比较了不同的版本?在我的系统上,在内部循环中创建一个新笔刷仍然比在mac外部或内部创建和冻结笔刷要快
SolidColorBrush[] brushes = new SolidColorBrush[2];
for (int i = 0; i < brushes.Length; i++)
{
    var brush = new SolidColorBrush(new Color());
    brush.Freeze();
    brushes[i] = brush;
}
int brushIx = 0;

Action macroStep = () =>
{
    dataB = new int[100, 100];
    var brush = brushes[brushIx++ % brushes.Length];
...
    rectangles[x, y].Fill = dataB[x, y] == 0
        ? brush
        : Brushes.Black;
    data = dataB;
};