在不同的线程中渲染控件

时间:2013-03-13 11:00:57

标签: c# wpf multithreading visifire

我的应用程序(migradoc)中有PDF导出。为了避免冻结GUI,我想将此Export作为单独的Thread运行。 PDF还嵌入了图表。为了使这些图表看起来像我在我的应用程序中使用的那些,我在Code中创建并呈现它们。 (的Visifire) 我的线程已经是STA,但是在运行WPF渲染命令时出现异常:

  

调用线程无法访问此对象,因为另一个线程拥有它

我的代码:

         chart.Measure(new Size(311, 180));
            chart.Arrange(new Rect(0, 0, 311, 180));
            chart.UpdateLayout();
            ExportToPng(new Uri("C:\\" + i + "c.png"), chart);

  public void ExportToPng(Uri path, Chart surface)

    {
        if (path == null) return;


        // Save current canvas transform

        Transform transform = surface.LayoutTransform;


        // reset current transform (in case it is scaled or rotated)

        surface.LayoutTransform = null;


        // Create a render bitmap and push the surface to it

        var renderBitmap =
            new RenderTargetBitmap(
                (int) surface.Width,
                (int) surface.Height,
                96d,
                96d,
                PixelFormats.Pbgra32);


        renderBitmap.Render(surface);


        // Create a file stream for saving image

        using (var outStream = new FileStream(path.LocalPath, FileMode.Create))

        {
            // Use png encoder for our data

            var encoder = new PngBitmapEncoder();


            // push the rendered bitmap to it

            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));


            // save the data to the stream

            encoder.Save(outStream);
        }


        // Restore previously saved layout

        surface.LayoutTransform = transform;
    }

我已经尝试过调度此命令,但我仍然会遇到相同的错误。

  DispatcherHelper.UIDispatcher.BeginInvoke((Action)(() =>
        {
                        chart.Measure(new Size(311, 180));
                        chart.Arrange(new Rect(0, 0, 311, 180));
                        chart.UpdateLayout();
                        ExportToPng(new Uri("C:\\" + i + "c.png"), chart);
                    }));

1 个答案:

答案 0 :(得分:0)

你需要传递任何对象的副本,这是GUI线程的一部分,因为GUI线程拥有它们,这就是为什么它们无法在其他线程中访问。像图表对象一样,您需要创建图表对象的副本,然后将其传递给线程,以便对象的所有者是您的新线程。

如果你需要在同一个GUI线程上渲染它们,那么只有机会在同一个线程上渲染它们并等待操作完成。