C#, WPF, Helix Toolkit. I am trying to save an image from a HelixViewport3D
viewport (as described here) and am still having problems.
Intended method: Render image to viewport and simply save that using Viewport3DHelper.SaveBitmap()
or similar method.
Viewport3DHelper.SaveBitmap(helixPlot.Viewport, @"E:\test.bmp", null, 4, BitmapExporter.OutputFormat.Png);
The problem with that: It runs but the captured image is blank. My best guess is that Helix Toolkit is rendering asynchronously(?) There is no image there to grab at the time that I am saving it.
Possible workaround 1: Respond to an event once rendering is complete.
The problem with that: There is no suitable event to subscribe to.
Possible workaround 2: Add an in-line delay to allow the image to render before saving it. (Clunky and unreliable, but would be a step in the right direction).
Thread.Sleep(2000);
Viewport3DHelper.SaveBitmap(helixPlot.Viewport, @"E:\test.bmp", null, 4, BitmapExporter.OutputFormat.Png);
The problem with that: The image doesn't get displayed until my code execution completes. If I add a delay of 10 seconds, I just get a blank screen for an additional 10 seconds.
Possible workaround 3: Add a timer so that the image will be rendered and I can then save the image from the timer elapsed event.
System.Timers.Timer timer = new System.Timers.Timer();
...
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = 2000; // two seconds
timer.Start();
....
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Viewport3DHelper.SaveBitmap(helixPlot.Viewport, @"E:\test.bmp", null, 4, BitmapExporter.OutputFormat.Png);
}
The problem with that: Although the image is rendered successfully and is there for the taking, the timer is running in a different thread to I cannot reference the HelixPlot control from the event handler. I get:
System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'
Possible workaround 4: Run the timer in the UI thread using Timer.SynchronizingObject
The problem with that: It doesn't seem to be possible to do this easily/simply in WPF. I can do it with a lot of additional code and at the moment this may be my best available option, but it seems strongly sub-optimal for reasons of verbosity and lack of robustness.
Is there not some reasonably straightforward way of achieving what I am trying to do?
The root of the problem seems to be that the image is not rendered to the viewport until the calling method has finished executing. I don't really understand why this is.
EDIT: I have been told on another forum that Helix Toolkit is rendering on the WPF composite render thread. However, after some Googling I am still none the wiser as to how I can wait for this rendering to complete.