I have a PDF Export in my Application (migradoc). To avoid freezing the GUI i want to run this Export as seperate Thread. The PDF has also Charts embedded in it. To make those Charts look like the ones i use in my application i create and render them in Code. (visifire) My Thread is already STA, but i get an Exception when running the WPF render Commands:
The calling thread cannot access this object because a different thread owns it
My Code:
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;
}
I already tried to dispatch this Commands, but i still keep getting the same Error.
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);
}));
you need to pass copy of any object which is the part of GUI thread as the GUI thread own them and that's why they can't be access in other thread. like you chart object you need to create a copy of chart object and then pass it into the thread so the owner of the object is your new thread.
If you need to render these on the same GUI thread then only chance is to render these on the same thread and wait to operation to complete.