C# 加快在WPF中将对象添加到画布的速度
我有一个C# 加快在WPF中将对象添加到画布的速度,c#,wpf,optimization,canvas,C#,Wpf,Optimization,Canvas,我有一个Canvas,我在WPF中使用它来绘制许多彩色矩形,但是当它们被添加时,程序运行得非常慢。我尝试过不同的选择,比如将它们添加到数组中,然后一次将它们全部添加,并使用图像来显示它们,而不是使用画布,但它们似乎没有起到多大作用。我在一个线程中有引导绘图的代码,但是由于C#规则,我必须在主线程中有绘图部分。我还应该指出,问题不在于我的计算机(它运行的是带有14GB DDR2 RAM的Intel Core i7) 这是添加矩形的代码。它运行了83000多次 private void Ad
Canvas
,我在WPF中使用它来绘制许多彩色矩形,但是当它们被添加时,程序运行得非常慢。我尝试过不同的选择,比如将它们添加到数组中,然后一次将它们全部添加,并使用图像来显示它们,而不是使用画布,但它们似乎没有起到多大作用。我在一个线程中有引导绘图的代码,但是由于C#规则,我必须在主线程中有绘图部分。我还应该指出,问题不在于我的计算机(它运行的是带有14GB DDR2 RAM的Intel Core i7)
这是添加矩形的代码。它运行了83000多次
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);
}
private void AddBlock(双左、双顶、双宽、双高、画笔颜色)
{
if(this.Dispatcher.Thread!=Thread.CurrentThread)
{
this.Dispatcher.Invoke(新操作(this.AddBlock)、左、上、宽、高、颜色);
返回;
}
矩形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似乎没有可行的解决方案
有什么建议吗?使用OnRender方法
我创建了一个继承Canvas的类,并重写OnRender方法来获取DrawingContext并使用它来绘制。因此,在代码中,我不会将rect添加到画布中,而是添加到新类中的rect列表中,并调用invalidateevisial()代码>完成add后使用Dispatcher
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);
}
}
}
准备就绪后,应在dispatcher上进行刷新
canvas.InvalidateVisual();
这似乎是使用WPF的最快方法,您可能不需要等到GDI+或pinvoke。在我的系统中进行测试期间,原始代码大约花费了500 ms
来渲染830个矩形
,几何体大约花费了400 ms来渲染相同的矩形,其中,与此方法一样,在100 ms的时间内渲染83000个矩形
我还建议您添加一些缓存,以避免过度渲染
使用几何体的解决方案
类级变量
GeometryGroup gGroup;
使用以下代码进行准备
DrawingBrush dBrush= new DrawingBrush();
gGroup = new GeometryGroup();
GeometryDrawing gDrawing = new GeometryDrawing(Brushes.Red, null, gGroup);
dBrush.Drawing = gDrawing;
Canvas.Background = dBrush
然后是你的代码
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)));
}
private void AddBlock(双左、双顶、双宽、双高、画笔颜色)
{
if(this.Dispatcher.Thread!=Thread.CurrentThread)
{
this.Dispatcher.Invoke(新操作(this.AddBlock)、左、上、宽、高、颜色);
返回;
}
//在几何绘图中添加颜色时,需要计算颜色
//当前为笔刷。前面定义了红色
添加(新矩形几何体(新矩形(左、上、宽、高));
}
此示例可能会帮助您实现相同的目标。我还将很快做一些实验,以更快地获得您想要的结果。您是否尝试使用几何体而不是矩形?@ub3rst4r-您可以使用轻量级drawingVisual在画布上绘制对象。参考代码让你开始。这不起作用,因为(a)我需要块是一种颜色,(b)它仍然很慢。我想要的是在线程上运行但能与WPF一起工作的东西(即使它涉及P/Invoke)。好的,给我一些时间,我能为你做点什么吗。更新了我的答案以使用OnRender方法,它非常快。我只需调整线程,使它能与该类一起工作,现在它很快就会更新!谢谢
DrawingBrush dBrush= new DrawingBrush();
gGroup = new GeometryGroup();
GeometryDrawing gDrawing = new GeometryDrawing(Brushes.Red, null, gGroup);
dBrush.Drawing = gDrawing;
Canvas.Background = dBrush
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)));
}