EDIT 1 :
Apparently, i have started to achieve a 3D rendering in WPF environment in an incorrect way. Ofc there is a solution for my question here below, but i suggest to read the update of Sheridan's answer and use his recommendations to achieve this. It's not only secure, but also better for performance. Although it's a bit complex to understand it, but once you understand it, you can start rendering multiple 3D applications in WPF. Thanks for your assistance Sheridan !
Question ;
i am quite new in WPF, and i want to design a continuous rendering (like in gaming applications) with WPF. I am using multithreading to provide a better UI control (start/stop button fe). Or the event could be disposed due of using an infinite loop to render the 3D world.
But, my problem is that when running the program, i get an Invalid operation was unhandled error. The issue is that there is an object which is a property of the main thread, thus the new thread might not access it.
from XAML file,
<Grid>
    <!-- ui controls omitted ... -->
    <Viewport3D Name="myViewport" ClipToBounds="True">
        <!-- all inits, camera, pos, ... -->
    </Viewport3D>
</Grid>
in main class;
/// <summary>this method is done to render the 3D app in other thread.</summary>
private void Runtime(Viewport3D vp) {
    System.Diagnostics.Debug.WriteLine("runtime ");
    Render3D r3d = new Render3D(vp);
    // actual startup
    while (keepRunning) {
        r3d.Init3D();
    }
}
/// <summary>this method toggles the game runtime</summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StartOrStop(object sender, RoutedEventArgs e) {
    keepRunning = !keepRunning;
    if (keepRunning) {
        buttonStartStop.Content = "Stop";
        // thread
        t1 = new Thread( () => Runtime(myViewport) );
        t1.Start();
    }
    else {
        buttonStartStop.Content = "Start";
        t1.Abort();
    }
}
The 3DViewport object is initialized in the XAML file. that's why i am passing it to the new thread, that it can create an object which is using that 3DViewport class.
Here below is a sample of the Render3D class.
// constructor
internal Render3D(Viewport3D v) {
    currViewport = v;
}
/// <summary>get called in loops to render gfx</summary>
internal void Init3D() {
    // clear rendered view
    ClearRenderWindow();
    // add landscape
    AddLandScape();
}
/// <summary>clear window to re-render gfx</summary>
private void ClearRenderWindow() {
    ModelVisual3D mv;
    // ***** error got caught here below ******
    for (int i = currViewport.Children.Count - 1; i >= 0; i--) {
        mv = (ModelVisual3D)currViewport.Children[i];
        if (mv.Content is DirectionalLight == false) currViewport.Children.Remove(mv);
    }
}
The error is caught at the currViewport.Children.Count method. As previously said, the issue is that the current thread doesn't have ownership of that object. It's the first time in my multithreading experience to face with this issue. I have searched around, but couldn't find a solution. 
Does anyone know how to pass the ownership of the Viewport3D-object, or a good workaround ?
Firstly, I would like to say that WPF is not a good framework for developing all but the simplest games... I would advise using a gaming framework like Microsoft's XNA instead.
However, if you insist on using WPF, then I would like to bring the CompositionTarget.Rendering event to your attention. It basically uses the frame rate of the host computer to render regulates graphics passes, avoiding the need to use timers.
You should also take a look at the How to: Render on a Per Frame Interval Using CompositionTarget page at MSDN for more helpful information and code examples.
Also, please read this extract from the book 'WPF Control Development Unleashed: Building Advanced User Experiences':
Some readers may recognize a similarity between this approach and higher-end graphics subsystems like DirectX. Do not mistake CompositionTarget.Rendering for a good injection point to create a WPF-based gaming graphics engine. High-end graphics and ultrahigh frame rates are not the goal of this particular aspect of WPF animation.
Similar to the DispatcherTimer approach, animations based on CompositionTarget.Rendering are also not time-bound. However, these events are synced with the render thread resulting in smoother animations than the DispatcherTimer. Also there is no need to start and stop a timer, although you may have to detach and attach the event handler to improve performance.
UPDATE >>>
Having discovered that this is just for a course project, I would ignore my previous comment and your code example so far. Don't try to create a new rendering system when there is one already. Instead, you should follow this approach:
Create data objects that implement the INotifyPropertyChanged interface and have X, Y, and DirectionVector (could be a Size struct) public properties.
Add a Move method (or Swim method for your Fish class) in which you update the data objects' X and Y properties dependant on the value of the DirectionVector property.
Add a ListBox control to your UI.
Create a collection property to hold your data objects, add items and bind the collection to the ListBox.ItemsSource property.
Create a DataTemplate to define what your Fish objects look like... you can use the Path class to draw them and even use a RotateTransform to rotate them (the angle can be calculated from the DirectionVector property). In the DataTemplate, you can bind the X and Y properties to the `Margin' property.
Finally, add an infinite loop (possibly with a break out option) and in that loop, iterate through the collection of data objects and call Move() on each one. This will update the data objects' positions in the ListBox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With