【发布时间】:2016-04-01 02:42:14
【问题描述】:
一个带有面板和框的表单,用户单击一个框,然后会出现一个标签,说“框命中”。
我有一个工作版本的代码,但我尝试重新排列它以尝试使其更高效,但我发现我目前遇到了这个异常。
我不明白为什么会发生此异常,我希望能够对其进行故障排除,但我也不知道该怎么做。我已经把它缩小到它是什么线。但除此之外我不知道。
单击框时会发生错误。因此执行面板的mousedown。
所有控件,例如面板、标签都是以编程方式生成的,因此希望任何人都可以复制/粘贴代码更改类名并重现我得到的异常。
我在网上读到,即使不是真的内存不足,笔也可能会产生内存不足异常,但它只是抛出该异常,尽管这仍然没有告诉我为什么或如何避免它,所以我可以了解如何在笔不会引发异常的情况下编写代码。
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!
}
}
}
【问题讨论】:
-
您在 Paint 事件处理程序中泄漏了一个 Graphics 对象。也许还有更多,一旦操作系统确定您泄漏太多并且不会让您再创建,异常就会变得不稳定。使用任务管理器,进程选项卡并添加 GDI 对象和用户对象的列,以便您可以看到泄漏的累加。
-
@HansPassant 谢谢.. 我仍然在同一行得到相同的异常,(在 p_MouseDown 过程中),即使我将
using添加到绘图事件处理程序中的图形对象。我已经在我的问题中添加了一条注释。 -
@HansPassant 刚刚检查了用户对象和 GDI 对象,当我运行它时以及发生异常时它们都是 32 和 37。
-
@barlop 也许是因为我在全球范围内声明了一个。我想如果我只有一个图形路径并更改点,那么在内存方面更好的设计会是
-
一个有趣的稍微相关的问题stackoverflow.com/questions/34373828/…
标签: c# winforms visual-studio memory idisposable