在图画形状结冰的窗口

时间:2012-04-21 14:42:55

标签: .net wpf multithreading drawing

我的WPF窗口中有Canvas,我想绘制大量的形状(大约数十万个或更多)。像这样:

<Window>
<Canvas>
    <!--<Shape1/>
    <Shape2/>
    ... and so on ... -->
</Canvas>
</Window>

要绘制形状,我有一个方法可以完成这样的工作:

public void DrawShape()
{
    // Create the shape
    ShapeT MyShape = new ShapeT();
    // Set shape's properties (like Width, Fill, ...)

    // Add shape as MyCanvas children.
    MyCanvas.Children.Add(MyShape);
}

然后绘制,例如,我做了四万个形状:

for (uint i = 0; i < 0x9C40; ++i)
     DrawShape();

问题是:

  1. 在未绘制所有数字之前,即在循环完成之前,不会绘制任何数字并且我的窗口始终没有响应。

  2. 即使在完成循环之后,在视频上绘制数字之前仍需要几秒钟,我的窗口仍然会被冻结。

  3. 我尝试使用Dispatcher

    Dispatcher.BeginInvoke(DispatcherPriority.Background, new MyDrawDelegate(DrawShape));
    

    我试图创建一个新线程:

    Thread DrawThread = new Thread(new ThreadStart(DrawShape));
    DrawThread.SetApartmentState(ApartmentState.STA);
    DrawThread.Priority = ThreadPriority.Lowest;
    DrawThread.Start();
    

    但没有变化。 我该如何解决这些问题?

    PS:出于性能原因,我使用Visual而非Shape对象绘制形状。

2 个答案:

答案 0 :(得分:0)

据我所知,WPF(直到3.5)只允许一个线程访问WPF对象,所以我认为你需要优化它而不是使用线程。

所以例如:你是否需要所有的形状都显示出来?你能加载它们的一部分并在第二次加载其他对象吗?

答案 1 :(得分:0)

当您使用Dispatcher时,可能是您的ArangePass花费很长时间来呈现对UI的更新更改的情况。 您可以通过添加以下代码段来使您的父容器等待:

  using (var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(yourRenderTarget) == null ? yourRenderTarget: null) })
        {
            // Flush the dispatcher queue
            yourRenderTarget.Dispatcher.Invoke(DispatcherPriority.Background, 
            new Action(() => {/*required action*/ }));
         }

尝试一下,它对我有用.. !!