简体   繁体   中英

Error when drawing line in Graphics.DrawLine C# Visual Studio

private void Form1_Paint(object sender, PaintEventArgs e)
    {
        Graphics l = e.Graphics;
        Pen p = new Pen(Color.Black, 1);
        float angle = 0;
        float len = 100;
        PointF ori = new PointF(Width/2, 0);    
        PointF bob = new PointF(Width/2, len);
        while(true)
        {

            bob.X = ori.X + len * (float)Math.Sin(angle);
            bob.Y = ori.Y + len * (float)Math.Cos(angle);
            angle += 0.001F;
            l.DrawLine(p, ori.X, ori.Y, bob.X, bob.Y);
            l.DrawEllipse(p, bob.X - 15, bob.Y, 30, 30);
            if(angle == 360)
            {
                break;
            }
            l.Dispose();
        } 
    }

The error line is l.DrawLine(p, ori.X, ori.Y, bob.X, bob.Y). Error type: System.ArgumentException. Error Message: Parameter is not valid.

At first I thought the issue was with the floats but the DrawLine allows for such datatypes. It loops through once the error seems to occur when angle>0. Its magnitude doesn't seem to be the issue. Any help would be much appreciated. Thanks in advance. [UPDATE] Error seems to be with the l.Dispose

The problem is in the wrong Dispose call:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Graphics l = e.Graphics;

    // Pen is IDisposable, that's why why wrap it into "using": it's you who created it 
    using (Pen p = new Pen(Color.Black, 1)) {
      float angle = 0;
      float len = 100;
      PointF ori = new PointF(Width/2, 0);    
      PointF bob = new PointF(Width/2, len);

      while(true)
      {
        bob.X = ori.X + len * (float)Math.Sin(angle);
        bob.Y = ori.Y + len * (float)Math.Cos(angle);
        angle += 0.001F;

        l.DrawLine(p, ori.X, ori.Y, bob.X, bob.Y);
        l.DrawEllipse(p, bob.X - 15, bob.Y, 30, 30);

        // angle is float, that's why == is not recommended:
        // (you can well have 359.99999999999999) and thus == will never be true
        if (angle >= 360) 
            break;

        // l.Dispose(); // <- Wrong: it's not you who've created it
                        // (let system Dispose it) 
      } 
    }
}

As an enhancement to @Dmitry's answer, I can offer this advice:

As a general rule, you shouldn't call Dispose on an object that you do not control the lifetime of. You are getting an existing Graphics instance from the Paint event. The control that raised the Paint event is what created that Graphics object, so it is responsible for calling Dispose on it when it is done with it, not you.

When you call Dispose on an object that you don't control, you effectively "rip the rug out from under" that code. This is bad, because that code could be expecting the instance to still be alive so that it can perform other operations on it. By disposing it, you don't give it that chance.

You are doing the correct thing with your Pen instance, p , though. You create it during the using statement, so you are responsible for it. The Using handles that by automatically calling Dispose when execution leave the block.

If you had created the Graphics instance yourself, with something like Graphics.FromImage`, then you would be responsible for cleaning it up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM