c# Pen 抛出 OutOfMemoryException
c# Pen throws OutOfMemoryException
一个带有面板和框的表单,用户单击一个框,然后会出现一个标签,上面写着 "box hit"。
我有一个代码的工作版本,但我试图重新安排它以试验使其更有效,我发现我目前遇到了这个异常。
我不明白为什么会出现这个异常,我希望能够解决它,但我也不知道该怎么做。我已经把它缩小到它是什么线。但除此之外我就不知道了。
点击框时出现错误..所以面板的mousedown被执行了。
所有控件,例如面板、标签都是以编程方式生成的,因此希望任何人都可以 copy/paste 代码更改类名并重现我得到的异常。
我在网上读到笔可能会产生内存不足异常,即使它并没有真正用完内存,但它只是抛出那个异常,尽管那仍然没有告诉我为什么或如何避免它,所以我可以理解如何在笔不抛出该异常的情况下编写代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication17
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
GraphicsPath[] gps = new GraphicsPath[9];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262);
points[0][1] = new Point(28, 257);
points[0][2] = new Point(27, 284);
points[0][3] = new Point(16, 285);
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][2] = new Point(61, 277);
points[1][3] = new Point(49, 278);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][2] = new Point(99, 275);
points[2][3] = new Point(86, 274);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][2] = new Point(139, 279);
points[3][3] = new Point(126, 277);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][2] = new Point(175, 287);
points[4][3] = new Point(164, 284);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][2] = new Point(209, 295);
points[5][3] = new Point(198, 292);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][2] = new Point(240, 300);
points[6][3] = new Point(229, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][2] = new Point(275, 300);
points[7][3] = new Point(262, 301);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][2] = new Point(311, 295);
points[8][3] = new Point(298, 296);
panel.Paint += thepanel_Paint;
// I can see that I can remove all the braces, but anyhow.
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
}
}
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
//GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
bool cond1=false;
bool cond2=false;
cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
cond2 = gps[i].IsVisible(new Point(mea.X, mea.Y));
if (cond1 == true ||
cond2 == true)
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
附带说明一下,这是重新排列之前的代码,它可以正常工作,但不会抛出异常(尽管它可能效率低下,因为每次鼠标按下时它都会添加多边形以确定点击了哪个,而实际上是只需要做一次)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262); //left top
points[0][1] = new Point(28, 257); //right top
points[0][2] = new Point(27, 284); //right bottom
points[0][3] = new Point(16, 285); //left bottom
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][3] = new Point(49, 278);
points[1][2] = new Point(61, 277);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][3] = new Point(86, 274);
points[2][2] = new Point(99, 275);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][3] = new Point(126, 277);
points[3][2] = new Point(139, 279);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][3] = new Point(164, 284);
points[4][2] = new Point(175, 287);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][3] = new Point(198, 292);
points[5][2] = new Point(209, 295);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][3] = new Point(229, 300);
points[6][2] = new Point(240, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][3] = new Point(262, 301);
points[7][2] = new Point(275, 300);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][3] = new Point(298, 296);
points[8][2] = new Point(311, 295);
panel.Paint += thepanel_Paint;
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black,1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
if (gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen) == true || gps[i].IsVisible(new Point(mea.X, mea.Y)))
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
已添加
回复汉斯的评论。
我发现我在面板绘制过程中错过了那个图形对象的 using
。但是如果我添加它,那么,使用这段代码。
using(Graphics gg = panel.CreateGraphics())
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Black, 1), gps[i]);
}
我仍然在 p_MouseDown
过程的 cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
行遇到同样的异常。
进一步添加
Q 得到了回答,但还有一件更奇怪的事情。我试图创建一个简单的程序来给出相同的异常,但程序没有崩溃或 运行 正确所以也许 运行时间错误发生与否并不能清楚地预测。在这里,我希望出现内存不足异常,或者至少有两个消息框,而不仅仅是一个消息框,我没有发现异常,只有一个消息框。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace blah
{
public partial class Form1 : Form
{
Pen p;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("sadf"); //displays
MessageBox.Show(p.Color.ToString()); // doesn't display a messagebox at all!
}
}
}
除了初始化 Pen
和一些其他未使用的对象外,您还使用 using
关键字来创建 GraphicsPath
。那么当你退出 using
语句时会发生什么......是的,对象被释放了。
相反,请尝试创建您的路径,例如
for (int i = 0; i < 9; i++)
{
gps[i] = new GraphicsPath();
gps[i].AddPolygon(points[i]);
}
所以这真的与应用获取 OutOfMemory
无关...但是,是的,异常至少会产生误导。
在您的应用程序上方使用可以正常工作,但正如@Hans Passant 所说,您仍然在泄漏内存。
编辑:
这是您的代码的重写,只是 "because" :)。希望对您有所帮助 and/or 有道理。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
// It's preferred to use established naming conventions,
// such as prefixing private fields with "_".
// Declaring access modifiers explicitly, even default modifier
// "private", is advised because it makes reading thousands lines of code
// that much easier (one can expect first keyword to be access modifier)
public partial class Form1 : Form
{
// For convenience and readability,
// I'd prefer Lists and List-of-Lists over arrays
private readonly List<List<Point>> _points = new List<List<Point>>();
private readonly List<GraphicsPath> _graphicsPaths = new List<GraphicsPath>();
public Form1()
{
InitializeComponent();
// Points to create paths from
_points.AddRange(new[]
{
new List<Point>
{
new Point(19, 62),
new Point(28, 57),
new Point(27, 84),
new Point(16, 85)
},
new List<Point>
{
new Point(52, 53),
new Point(62, 50),
new Point(61, 77),
new Point(49, 78)
},
new List<Point>
{
new Point(87, 49),
new Point(100, 48),
new Point(99, 75),
new Point(86, 74)
}
});
// Create GDI graphics paths
foreach (List<Point> points in _points)
{
GraphicsPath path = new GraphicsPath();
path.AddPolygon(points.ToArray());
_graphicsPaths.Add(path);
}
}
private void Form1_Load(object sender, EventArgs e)
{
// Adjust form
Height = 200;
Width = 100;
// Create label and panel
// No need for these to be private fields
Label label = new Label
{
Text = @"Border clicked",
Visible = false
};
// Create panel
Panel panel = new Panel
{
Height = 400,
Width = 400,
BackColor = Color.White,
BackgroundImageLayout = ImageLayout.Stretch
};
// Paint event handler.
// Personally I prefer inline anonymous methods
// over named methods when logic is simple
// and it's not being reused
panel.Paint += (o, args) =>
{
// 'using' because we want to get rid of Graphics
// and Pen when we are done drawing paths
using (Graphics graphics = panel.CreateGraphics())
{
using (Pen pen = new Pen(Color.Blue, 3))
{
foreach (GraphicsPath path in _graphicsPaths)
graphics.DrawPath(pen, path);
}
}
};
// Mouse (down) event handler.
panel.MouseDown += (o, args) =>
{
// Get mouse point
Point mousePoint = new Point(args.X, args.Y);
// Again, we want to dispose Pen
using (Pen pen = new Pen(Color.Transparent, 0F))
{
// Get first path under mouse pointer
GraphicsPath path = _graphicsPaths.FirstOrDefault(p =>
p.IsOutlineVisible(mousePoint, pen));
if (path == null)
return;
// If found, "flash" our informative label
// in non-blocking way
Task.Run(() =>
{
label.Invoke((Action)(() => label.Visible = true));
Thread.Sleep(500);
label.Invoke((Action)(() => label.Visible = false));
});
}
};
// Add controls to containers
panel.Controls.Add(label);
Controls.Add(panel);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// This could be more reasonable place to dispose
// GDI Graphics path created earlier?
foreach (GraphicsPath path in _graphicsPaths)
path.Dispose();
_graphicsPaths.Clear();
}
}
}
一个带有面板和框的表单,用户单击一个框,然后会出现一个标签,上面写着 "box hit"。
我有一个代码的工作版本,但我试图重新安排它以试验使其更有效,我发现我目前遇到了这个异常。
我不明白为什么会出现这个异常,我希望能够解决它,但我也不知道该怎么做。我已经把它缩小到它是什么线。但除此之外我就不知道了。
点击框时出现错误..所以面板的mousedown被执行了。
所有控件,例如面板、标签都是以编程方式生成的,因此希望任何人都可以 copy/paste 代码更改类名并重现我得到的异常。
我在网上读到笔可能会产生内存不足异常,即使它并没有真正用完内存,但它只是抛出那个异常,尽管那仍然没有告诉我为什么或如何避免它,所以我可以理解如何在笔不抛出该异常的情况下编写代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication17
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
GraphicsPath[] gps = new GraphicsPath[9];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262);
points[0][1] = new Point(28, 257);
points[0][2] = new Point(27, 284);
points[0][3] = new Point(16, 285);
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][2] = new Point(61, 277);
points[1][3] = new Point(49, 278);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][2] = new Point(99, 275);
points[2][3] = new Point(86, 274);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][2] = new Point(139, 279);
points[3][3] = new Point(126, 277);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][2] = new Point(175, 287);
points[4][3] = new Point(164, 284);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][2] = new Point(209, 295);
points[5][3] = new Point(198, 292);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][2] = new Point(240, 300);
points[6][3] = new Point(229, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][2] = new Point(275, 300);
points[7][3] = new Point(262, 301);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][2] = new Point(311, 295);
points[8][3] = new Point(298, 296);
panel.Paint += thepanel_Paint;
// I can see that I can remove all the braces, but anyhow.
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
}
}
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
//GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
bool cond1=false;
bool cond2=false;
cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
cond2 = gps[i].IsVisible(new Point(mea.X, mea.Y));
if (cond1 == true ||
cond2 == true)
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
附带说明一下,这是重新排列之前的代码,它可以正常工作,但不会抛出异常(尽管它可能效率低下,因为每次鼠标按下时它都会添加多边形以确定点击了哪个,而实际上是只需要做一次)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262); //left top
points[0][1] = new Point(28, 257); //right top
points[0][2] = new Point(27, 284); //right bottom
points[0][3] = new Point(16, 285); //left bottom
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][3] = new Point(49, 278);
points[1][2] = new Point(61, 277);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][3] = new Point(86, 274);
points[2][2] = new Point(99, 275);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][3] = new Point(126, 277);
points[3][2] = new Point(139, 279);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][3] = new Point(164, 284);
points[4][2] = new Point(175, 287);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][3] = new Point(198, 292);
points[5][2] = new Point(209, 295);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][3] = new Point(229, 300);
points[6][2] = new Point(240, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][3] = new Point(262, 301);
points[7][2] = new Point(275, 300);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][3] = new Point(298, 296);
points[8][2] = new Point(311, 295);
panel.Paint += thepanel_Paint;
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black,1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
if (gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen) == true || gps[i].IsVisible(new Point(mea.X, mea.Y)))
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
已添加
回复汉斯的评论。
我发现我在面板绘制过程中错过了那个图形对象的 using
。但是如果我添加它,那么,使用这段代码。
using(Graphics gg = panel.CreateGraphics())
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Black, 1), gps[i]);
}
我仍然在 p_MouseDown
过程的 cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
行遇到同样的异常。
进一步添加
Q 得到了回答,但还有一件更奇怪的事情。我试图创建一个简单的程序来给出相同的异常,但程序没有崩溃或 运行 正确所以也许 运行时间错误发生与否并不能清楚地预测。在这里,我希望出现内存不足异常,或者至少有两个消息框,而不仅仅是一个消息框,我没有发现异常,只有一个消息框。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace blah
{
public partial class Form1 : Form
{
Pen p;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("sadf"); //displays
MessageBox.Show(p.Color.ToString()); // doesn't display a messagebox at all!
}
}
}
除了初始化 Pen
和一些其他未使用的对象外,您还使用 using
关键字来创建 GraphicsPath
。那么当你退出 using
语句时会发生什么......是的,对象被释放了。
相反,请尝试创建您的路径,例如
for (int i = 0; i < 9; i++)
{
gps[i] = new GraphicsPath();
gps[i].AddPolygon(points[i]);
}
所以这真的与应用获取 OutOfMemory
无关...但是,是的,异常至少会产生误导。
在您的应用程序上方使用可以正常工作,但正如@Hans Passant 所说,您仍然在泄漏内存。
编辑:
这是您的代码的重写,只是 "because" :)。希望对您有所帮助 and/or 有道理。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
// It's preferred to use established naming conventions,
// such as prefixing private fields with "_".
// Declaring access modifiers explicitly, even default modifier
// "private", is advised because it makes reading thousands lines of code
// that much easier (one can expect first keyword to be access modifier)
public partial class Form1 : Form
{
// For convenience and readability,
// I'd prefer Lists and List-of-Lists over arrays
private readonly List<List<Point>> _points = new List<List<Point>>();
private readonly List<GraphicsPath> _graphicsPaths = new List<GraphicsPath>();
public Form1()
{
InitializeComponent();
// Points to create paths from
_points.AddRange(new[]
{
new List<Point>
{
new Point(19, 62),
new Point(28, 57),
new Point(27, 84),
new Point(16, 85)
},
new List<Point>
{
new Point(52, 53),
new Point(62, 50),
new Point(61, 77),
new Point(49, 78)
},
new List<Point>
{
new Point(87, 49),
new Point(100, 48),
new Point(99, 75),
new Point(86, 74)
}
});
// Create GDI graphics paths
foreach (List<Point> points in _points)
{
GraphicsPath path = new GraphicsPath();
path.AddPolygon(points.ToArray());
_graphicsPaths.Add(path);
}
}
private void Form1_Load(object sender, EventArgs e)
{
// Adjust form
Height = 200;
Width = 100;
// Create label and panel
// No need for these to be private fields
Label label = new Label
{
Text = @"Border clicked",
Visible = false
};
// Create panel
Panel panel = new Panel
{
Height = 400,
Width = 400,
BackColor = Color.White,
BackgroundImageLayout = ImageLayout.Stretch
};
// Paint event handler.
// Personally I prefer inline anonymous methods
// over named methods when logic is simple
// and it's not being reused
panel.Paint += (o, args) =>
{
// 'using' because we want to get rid of Graphics
// and Pen when we are done drawing paths
using (Graphics graphics = panel.CreateGraphics())
{
using (Pen pen = new Pen(Color.Blue, 3))
{
foreach (GraphicsPath path in _graphicsPaths)
graphics.DrawPath(pen, path);
}
}
};
// Mouse (down) event handler.
panel.MouseDown += (o, args) =>
{
// Get mouse point
Point mousePoint = new Point(args.X, args.Y);
// Again, we want to dispose Pen
using (Pen pen = new Pen(Color.Transparent, 0F))
{
// Get first path under mouse pointer
GraphicsPath path = _graphicsPaths.FirstOrDefault(p =>
p.IsOutlineVisible(mousePoint, pen));
if (path == null)
return;
// If found, "flash" our informative label
// in non-blocking way
Task.Run(() =>
{
label.Invoke((Action)(() => label.Visible = true));
Thread.Sleep(500);
label.Invoke((Action)(() => label.Visible = false));
});
}
};
// Add controls to containers
panel.Controls.Add(label);
Controls.Add(panel);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// This could be more reasonable place to dispose
// GDI Graphics path created earlier?
foreach (GraphicsPath path in _graphicsPaths)
path.Dispose();
_graphicsPaths.Clear();
}
}
}