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.