I'm developing an app that shows some images (with some filter effects) using Canvas.
I've a static class called RendererBooster
. This class' RenderImage()
method renders the image with given effects WITH TASK on background and sets the MyViewer
coltrol's _bSource
property with the rendered image. (MyViewer is derived from Canvas)
On the other hand, I've a DispatcherTimer
inside the MyViewer
class. This DispatcherTimes
ticks every 2ms and checks if _bSource
is NOT NULL, calls the Canvas' InvalidateVisual()
method.
Everything is fine untill here.
My overridden OnRender()
method just draws that _bSource
to screen and sets _bSource
to NULL. After that, I get Cannot use a DependencyObject that belongs to a different thread than its parent Freezable
exception. Here is some sample code. What can I do to fix it?
RendererBooster
public static class RendererBooster
{
public static void RenderImage()
{
MyViewer viewer = ViewerManager.GetViewer();
Task.Factory.StartNew(() =>
{
unsafe
{
// render
// render again
// render again ..
// ...
// when rendering is done, set the _bSource.
viewer._bSource = BitmapSource.Create(sizeDr.Width, sizeDr.Height, 96, 96, PixelFormats.Prgba64, null, mlh.Buffer, sStride * sizeDr.Height, sStride);
}
});
}
}
MyViewer
public class MyViewer : Canvas
{
public BitmapSource _bSource = null;
private object _lockObj = new object();
public MyViewer()
{
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(2);
dt.Tick += dt_Tick;
dt.Start();
}
void dt_Tick(object sender, EventArgs e)
{
if (_bSource == null)
return;
InvalidateVisual();
}
protected override void OnRender(DrawingContext dc)
{
lock (_lockObj)
{
dc.DrawImage(_bSource, new System.Windows.Rect(new System.Windows.Point(0, 0), new System.Windows.Size(ActualWidth, ActualHeight)));
_bSource = null;
// this is the line that i get the exception
//Cannot use a DependencyObject that belongs to a different thread than its parent Freezable
}
}
}
NOTE: Why I'm doing the rendering work on an other function / class? Because rendering takes 3-4 seconds. If I render inside the OnRender() method, UIThread freezes the application.