C# WPF-在画布上并行绘制多个矩形

C# WPF-在画布上并行绘制多个矩形,c#,wpf,parallel-processing,drawing,C#,Wpf,Parallel Processing,Drawing,我有一个类BBox,它代表矩形——它包含矩形的坐标(x,y,宽度,高度)和颜色。然后我有这些BBox的列表,其中包含大约4000个BBox。我需要尽可能快地在画布上绘制存储在列表中的所有框。最有效的方法是什么 private List<BBox> FoundBoxes { get; set; } public void DrawBoxes(Canvas canvas) { foreach (var box in FoundBoxes)

我有一个类BBox,它代表矩形——它包含矩形的坐标(x,y,宽度,高度)和颜色。然后我有这些BBox的列表,其中包含大约4000个BBox。我需要尽可能快地在画布上绘制存储在列表中的所有框。最有效的方法是什么

    private List<BBox> FoundBoxes { get; set; }

    public void DrawBoxes(Canvas canvas)
    {
            foreach (var box in FoundBoxes)
            {
                var brush = box.getColor();
                System.Windows.Shapes.Rectangle rect;
                rect = new System.Windows.Shapes.Rectangle
                {
                    Stroke = brush,
                    Height = box.Height,
                    Width = box.Width,
                    StrokeThickness = 1
                };
                Canvas.SetLeft(rect, box.TopLeftX);
                Canvas.SetTop(rect, box.TopLeftY);
                canvas.Children.Add(rect);
            }
但它会抛出

System.InvalidOperationException: 'The calling thread must be STA, because many UI components require this.'
我知道为什么会发生这种情况,我试图找到解决办法,但什么都不适合我。例如,我尝试使用Dispatcher.Invoke(()=>运行它,或者使用新的线程运行它,如下所述:

Thread t = new Thread(delegate ()
{
    Parallel.ForEach(FoundBoxes, box =>
    {
      ...same method body...
    });
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();

但它仍然抛出了提到的异常。我如何解决这个问题?或者有没有更好/更有效的方法在画布上绘制多个对象?谢谢。

好的,我按照克莱门斯的建议使用解决了我的问题。现在,4000多个框是实时绘制的。

据我所知,wpf是如何工作的,对UI上下文的访问是顺序的l所以,并行化不会花费太多精力。可能你必须直接使用图形,自己处理其他UI内容(我的意思是鼠标处理、悬停等等)。wpf不是为超快速可视化而设计的。(你当然可以这样做)但是您必须比FrameworkElement更高。调查WPF FrameworkElement结构。这样更容易理解该做什么矩形有多少种不同的颜色?也许您可以为每种颜色使用一条路径,其中每种颜色都使用一个GeometryGroup作为其数据,并使用许多矩形几何。您还可以创建GeometryGroup为每个矩形添加绘图,并将它们添加到绘图组中,然后在绘图画笔中显示。对于4000个矩形,我需要200-300毫秒。另一种选择:WriteableBitmapEx。好的,谢谢你的建议,GeometryDrawing和WriteAbitMap看起来都很有用,我相信它们会完成这项工作。你真的帮助了我。
Thread t = new Thread(delegate ()
{
    Parallel.ForEach(FoundBoxes, box =>
    {
      ...same method body...
    });
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();