加快对象添加到画布在WPF [英] Speed up adding objects to Canvas In WPF

查看:230
本文介绍了加快对象添加到画布在WPF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个画布,我使用WPF中吸取许多彩色矩形来,但在程序运行确实正在增加时,他们放缓。我曾尝试不同的选择,如将它们添加到阵列并立即将所有这些,使用图片代替画布来dispay他们,但他们似乎并没有做太多。我领导了在一个线程绘图的编码,但由于C#的规则,我必须在主线程绘图的一部分。我还要指出,这个问题不是我的计算机(其运行的英特尔酷睿i7与14GB DDR2 RAM)。

I have a Canvas that I am using in WPF to draw many colored rectangles to but the program is running really slow when they are being added. I have tried different options, such as adding them to an Array and adding them all at once and using a Image instead of a Canvas to dispay them, but they didn't seem to do much. I have the coding leading up the drawing in a thread, but because of C# rules, I have to have the drawing part in the main thread. I should also note that the problem isn't my computer (its running Intel Core i7 with 14GB DDR2 RAM).

这是code,增加了矩形。它跑了83,000次。

This is the code that adds the rectangles. It is ran over 83,000 times.

    private void AddBlock(double left, double top, double width, double height, Brush color)
    {
        if (this.Dispatcher.Thread != Thread.CurrentThread)
        {
            this.Dispatcher.Invoke(new Action<double, double, double, double, Brush>(this.AddBlock), left, top, width, height, color);
            return;
        }

        Rectangle rect = new Rectangle() { Width = width, Height = height, Fill = color, SnapsToDevicePixels = true };

        this.canvas.Children.Add(rect);

        Canvas.SetLeft(rect, left);
        Canvas.SetTop(rect, top);
    }

注意:正如我在下面留言说,我想的东西,使得它能够在一个单独的线程(即使它涉及到用的P / Invoke的工作)上运行,因为似乎没有一个可行的解决方案,只是使用C#和WPF。

NOTE: As I stated in a comment below, I would like something that allows it to run on a seperate thread (even if it involves working with P/Invoke) as there doesn't seem to a viable solution to just using C# and WPF.

有什么建议?

推荐答案

使用方法的OnRender

我创建了一个类继承帆布,并覆盖的OnRender方法来获得的DrawingContext,并用它来绘制。所以在code我不添加rects到画布上,而是在新的类矩形列表和电话 InvalidateVisual();使用Dispatcher一次我与加做

I created a class inheriting Canvas, and override the OnRender method to get the DrawingContext and used it to draw. so in the code I dont add rects to the canvas but to the rect list in new class and call InvalidateVisual(); using Dispatcher once I am done with add.

class MyCanvas:Canvas
{
    public class MyRect
    {
        public Rect Rect;
        public Brush Brush;
    }

    public List<MyRect> rects = new List<MyRect>();

    protected override void OnRender(System.Windows.Media.DrawingContext dc)
    {
        base.OnRender(dc);
        for (int i = 0; i < rects.Count; i++)
        {
            MyRect mRect = rects[i];
            dc.DrawRectangle(mRect.Brush, null, mRect.Rect);
        }
    }
}

XAML

<l:MyCanvas x:Name="canvas"/>

添加rects

to add the rects

private void AddBlock(double left, double top, double width, double height, Brush color)
{
    canvas.rects.Add(new MyCanvas.MyRect() { Brush = color, Rect = new Rect(left, top, width, height) });
}

刷新准备好后,应在调度员进行

refresh when ready, should be made on dispatcher

canvas.InvalidateVisual();

这似乎是在WPF绘制最快的方式,你可能不需要去到GDI +或PInvoke的。在我的系统测试原来的code约了 500毫秒渲染 830 rects 和几何大约400毫秒花渲染一样,在这里,因为这种方法呈现的 83000 rects 在不到 100毫秒

This seems to be the fastest way to draw in WPF, you may not need to go till GDI+ or pinvoke. During tests in my system original code took approx 500 ms to render 830 rects and geometry took approx 400 ms to render the same, where as this approach rendered 83,000 rects in less then 100 ms

此外,我会建议你添加一些缓存,以避免过分渲染

Also I would advice you to add some caching to avoid rendering excessively

使用几何形状的解决方案

类级别的变量

GeometryGroup gGroup;

prepare使用以下code

prepare using the following code

DrawingBrush dBrush= new DrawingBrush();
gGroup = new GeometryGroup();
GeometryDrawing gDrawing = new GeometryDrawing(Brushes.Red, null, gGroup);
dBrush.Drawing = gDrawing;
Canvas.Background = dBrush

然后是你的code

then comes your code

private void AddBlock(double left, double top, double width, double height, Brush color)
{
    if (this.Dispatcher.Thread != Thread.CurrentThread)
    {
        this.Dispatcher.Invoke(new Action<double, double, double, double, Brush>(this.AddBlock), left, top, width, height, color);
        return;
    }
    //color need to figure out as it is added in GeometryDrawing 
    //currently Brushes.Red defined earlier
    gGroup.Children.Add(new RectangleGeometry(new Rect(left, top, width, height)));
}

这样本可能帮你实现相同。我还会做一些实验很快得到你想要的结果了更快的方法。

This sample may help you achieve the same. I'll also do some experiment soon to get your desired result in a much faster way.

这篇关于加快对象添加到画布在WPF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆