Resolved ?? Exception thrown: 'System.InvalidOperationException' in PresentationFramework.dll

GregJ7

Member
Joined
Nov 23, 2024
Messages
20
Programming Experience
10+
I built a simple app to draw a 30x30 grid of lines (30x31x2 individuals lines, not drawn as 30x30 rectangles). The first attached file is a snapshot of it running. It can be resized and the grid dynamically resizes with it. Then I discovered that XAML was causing me more trouble for logically structuring my code than I found acceptable, so I (following some YouTube directions) built an empty WPF app and deleted the .xaml files and their associated code behind .cs files. I added a entry point class and Main() and it would build and run. So I added back much of the code to draw the grid. Now I am getting a really esoteric bug, which I attribute to my project settings, because I have seen the code work (although I have since changed it somewhat), but I am several thousand hours short of the experience needed to figure out what is wrong.

Exception thrown: 'System.InvalidOperationException' in PresentationFramework.dll
The program '[34696] Test.exe' has exited with code 3221226525 (0xc000041d).

The exception is thrown in a call to a Window's AddChild(). There is no normal Exception dialog box. It just exits silently with the above lines of output.

It is the second time AddChild() is called that I get the error. If I stop adding children after the first time, the grid (with just one line) displays correctly.

I have attached a .zip of the solution. If anyone can spend a little time looking at this, I would greatly appreciate it. There is no apparent way forward for me to debug it myself. I'm not going to be able to learn the under-the-hood details of project settings, dependencies, and references anytime soon.
 

Attachments

  • Output.jpg
    Output.jpg
    390.2 KB · Views: 4
  • Test.zip
    4.8 KB · Views: 3
How did you resolve the issue?
 
By deciding I needed to learn how to build a WPF VS project up from an empty .NET project. Other people that have gotten the error in this base post never found out what the problem was.
 
After exploring various frameworks, it turns out that Windows Forms was what I was looking for. Unfortunately, its OnPaint() (drawing a couple thousand lines) runs and redraws so slowly that I am back to WPF.
 
The WM_PAINT message has the lowest priority in the Windows message queue.

If you want something faster, use P/Invoke for DirectDraw or DirectX, or find a managed wrapper for SFML.
 
I have a strange feeling that the code that you are trying to port was written for "immediate mode" while you are trying to use WPF drawing is "retained mode".

If it truly is "immediate mode" code -- which is more appropriate for WinForms, you'll need to be very efficient in your WinForms paint event handler code. Pre-create your pens and brushes and reuse them through out the life time instead of creating them each paint call. Look at the incoming paint event arguments to see what areas needs to be repainted -- you might not have to redraw the entire screen.

In your game loop, be efficient. Instead of invalidating the full screen, just invalidate the parts of the screen that change.
 
I looked briefly at Cocos2d, but hadn't heard of SFML. I didn't look at DirectX, assuming it was too much work for simple drawings, although now that I think about it, I should be able to find someone else's code for most of it. All I'm doing is drawing a lot of lines in a Window on a Canvas. Thanks for your posts. I'll now look at SFML and DirectX a little closer.
 
I seem to be getting pretty good 12 frames per second with 2000 lines with this code. Please excuse the ugly quick and dirty code. I was just trying to get somthing running to see how bad the performance was.

MainWindow.xaml:
<Window x:Class="WpfLines.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfLines"
        mc:Ignorable="d"
        Title="MainWindow" Height="768" Width="1024" Loaded="Window_Loaded">
    <Canvas Name="_canvas" Background="Black">
    </Canvas>
</Window>

MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WpfLines
{
    public partial class MainWindow : Window
    {
        const int WindowWidth = 1024;
        const int WindowHeight = 768;
        const int MaxVelocity = 5;
        const int MaxLines = 1000;
        const int FramesPerSecond = 12;

        class MovingLine
        {
            static readonly Random _random = new();

            static byte GetRandomByte()
                => (byte)_random.Next(256);

            static Color GetRandomColor()
                => Color.FromRgb(GetRandomByte(), GetRandomByte(), GetRandomByte());

            static int GetRandomVelocity()
            {
                var direction = _random.Next(100) > 50 ? 1 : -1;
                var magnitude = _random.Next(1, MaxVelocity);
                return direction * magnitude;
            }

            class EndPoint
            {
                public int X = _random.Next(WindowWidth);
                public int Y = _random.Next(WindowHeight);
                public int DeltaX = GetRandomVelocity();
                public int DeltaY = GetRandomVelocity();

                static void UpdateAxis(ref int a, ref int delta, int max)
                {
                    a += delta;
                    if (a < 0)
                    {
                        a = 0;
                        delta *= -1;
                    }
                    if (a >= max)
                    {
                        a = max - 1;
                        delta *= -1;
                    }
                }

                public void Update()
                {
                    UpdateAxis(ref X, ref DeltaX, WindowWidth);
                    UpdateAxis(ref Y, ref DeltaY, WindowHeight);
                }
            }

            public Line Line { get; init; } = new()
                                              {
                                                  StrokeThickness = 1,
                                                  Stroke = new SolidColorBrush(GetRandomColor())
                                              };
            readonly EndPoint _p1 = new();
            readonly EndPoint _p2 = new();

            public MovingLine()
                => UpdateLine();

            void UpdateLine()
            {
                Line.X1 = _p1.X;
                Line.Y1 = _p1.Y;
                Line.X2 = _p2.X;
                Line.Y2 = _p2.Y;
            }

            public void Update()
            {
                _p1.Update();
                _p2.Update();
                UpdateLine();
            }
        }

        public MainWindow()
            => InitializeComponent();

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var movingLines = Enumerable.Range(0, MaxLines)
                                        .Select(_ => new MovingLine())
                                        .ToList();
            movingLines.ForEach(l => _canvas.Children.Add(l.Line));

            var timer = new DispatcherTimer(DispatcherPriority.Normal);
            timer.Interval = TimeSpan.FromMilliseconds(1000 / FramesPerSecond);
            timer.Tick += (o, e) => movingLines.ForEach(l => l.Update());
            timer.Start();
        }
    }
}
 
Actually, if I'm willing to consider something like DirectX (after seeing how easy it is to use), I'm more likely to investigate an OpenGL wrapper. But right now I am dealing with learning overload, which is directing me toward simple things atm, but that will eventually pass.
 
Back
Top Bottom