1

In my robot control program, there should be a 3D model of the robot moving simultaneously with a real robot. I uploaded the 3D model and update its position after releasing the Slider with the mouse. Everything works, but with a real time update of the model, the entire application freezes.

How to draw a new robot model every 0.1 sec so that drawing does not slow down the display of other information on the screen and does not interfere with keystrokes?

Thread ThreadUpdateRobot = new Thread(new ThreadStart(OnPointAsync));
ThreadUpdateRobot.Start();
public void OnPoint()
{
    Dispatcher.Invoke(() => UpdateObjectZveno(angleFor3D));
    Dispatcher.Invoke(() => pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(OnPaint));
    Dispatcher.Invoke(() => pictureBox.Invalidate());
}

private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    for (int i = 0; i < device.Segments.Count; i++)
        DrawSegment(e.Graphics, device.Segments[i], colors[i % colors.Length], false);
}
private void DrawSegment(Graphics gr, Segment segment, System.Drawing.Color color, bool debugMode)
{
    var model = segment.VisualMesh;
    var scaleM = Matrix4x4.CreateScale(scale / 2);               //scale matrix
    var translateM = Matrix4x4.CreateTranslation(position);      //offset matrix
    var paneXY = new Matrix4x4() { M11 = 1f, M22 = 1f, M44 = 1f }; //projection matrix

    var m = scaleM * translateM * paneXY; //total matrix
    var vertices = model.Vertexes;

    if (debugMode)
    {
        vertices.Clear();
        vertices.Add(segment.Start);
        vertices.Add(segment.End);
    }

    //translate to world
    vertices = segment.ToWorld(vertices);

    //apply scale, offset and projection
    vertices = vertices.Select(v => Vector3.Transform(v, m)).ToList();

    if (debugMode)
    {
        var p1 = new PointF(vertices[0].X, vertices[0].Y);
        var p2 = new PointF(vertices[1].X, vertices[1].Y);

        using (var pen = new System.Drawing.Pen(color, 2))
            gr.DrawLine(pen, p1, p2);
        gr.DrawEllipse(Pens.Blue, p1.X - 3, p1.Y - 3, 6, 6);
        gr.DrawEllipse(Pens.Blue, p2.X - 3, p2.Y - 3, 6, 6);

        return;
    }

    //create graphicsPath
    using (var path = new GraphicsPath())
    {
        //create faces
        var prev = Vector3.Zero;
        var prevF = 0;
        foreach (var f in model.Fig)
        {
            if (f == 0) path.CloseFigure();
            var v = vertices[f];
            if (prevF != 0 && f != 0)
                path.AddLine(prev.X, prev.Y, v.X, v.Y);
            prev = v;
            prevF = f;
        }
        using (var pen = new System.Drawing.Pen(color))
            gr.DrawPath(pen, path);
    }
}
public MainWindow()
{
    System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
    pictureBox = new System.Windows.Forms.PictureBox
    {

        Anchor = System.Windows.Forms.AnchorStyles.Top,
        BackColor = System.Drawing.Color.White
    };
    pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(OnPaint);
    windowsFormsHost1.Child = pictureBox;


    UpdateObjectBase();

    pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(OnPaint);
}

XAML

<WindowsFormsHost Height="254" HorizontalAlignment="Left" Margin="714,339,0,0" Name="windowsFormsHost1" VerticalAlignment="Top" Width="467" Grid.Column="1" Grid.ColumnSpan="2" />
L_J
  • 2,351
  • 10
  • 23
  • 28
  • You are already using GDI+, which is a good idea to speed up drawing. But please, don't use pictureBox from winforms to display it. You can draw into bitmap and then create copy of it and invoke to display it inside wpf [Image](https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.image) control. – Sinatr Dec 18 '19 at 09:07
  • Yes, I know that pictureBox is a bad method, but my knowledge is not enough to transfer this to wpf – Vita Robertov Dec 18 '19 at 09:11
  • What exactly you don't know? Currently you are using `Graphics` from `Paint` event handle. Instead create own thread to contain draw loop, create there graphics [from bitmap](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.fromimage), draw as you do, then [convert image to BitmapSource](https://stackoverflow.com/a/22501616/1997232) and set `Image.Source` to it (don't forget to use `Dispatcher.Invoke`), repeat. [Here](https://stackoverflow.com/a/25618769/1997232) is a snippet which takes care about memory pressure. – Sinatr Dec 18 '19 at 09:40

0 Answers0