好吧,我正在创建一个应用程序,我正在使用 for 循环来基本上读取图像的每个像素,以寻找像素颜色的模式(简单的东西)无论如何,由于某种原因,我的应用程序只是锁定并且永远不会恢复正常.我一次又一次地遍历代码,但没有发现任何真正的问题。
我唯一注意到的是 ScanPixelsLater 中的 for 循环可能提前退出。我已经尽可能多地注释了代码,
private Point topLeftc, bottomLeftc, topRightc, bottomRightc;
/// <summary>
/// Starts the initial looping process, designed only to loop through ONCE, ScanPixelsLater takes over
/// </summary>
/// <param name="img">Image to scan</param>
public void ScanPixels(Bitmap img)
{
int whitePixel = 0;
for (int y = 100; y < img.Height; y++)
{
for (int x = 100; x < img.Width; x++)
{
if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
{
// img.SetPixel(x, y, Color.Green);
whitePixel++;
}
else { whitePixel = 0; }
if (whitePixel == 18)
{
whitePixel = 0;
topLeftc = new Point(x - 18, y);
DetectNextWhiteLine(topLeftc, img);
}
}
}
}
/// <summary>
/// First creates the TopRight value via using the last pixel in x range, and using the current Y value
/// Then a Y loop is started 10 pixels down, within this loop is another X loop which scans the X range
/// If 10 consecutive white pixels are found, the TopLeft X value and the current Y value are used to map the
/// BottomLeft and BottomRight coordinates. Finally a new Point is created which starts (x = 1) and (y = currentYValue + 2)
/// The ScanPixelsLater method is then called, passing the new Point (newLocation).
///
/// </summary>
/// <param name="p">The x and y value of where the pixels were found</param>
/// <param name="img">Image being used</param>
private void DetectNextWhiteLine(Point p, Bitmap img)
{
int whitePixel = 0;
topRightc = new Point(img.Width, topLeftc.Y);
for (int y = p.Y + 10; y < img.Height; y++)
{
for (int x = p.X - 5; x < img.Width; x++)
{
if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
{
whitePixel++;
}
else
{
whitePixel = 0;
}
if (whitePixel == 10)
{
bottomLeftc = new Point(topLeftc.X, y);
bottomRightc = new Point(img.Width, y);
Cords.Add(new Coordinates(topLeftc, topRightc, bottomLeftc, bottomRightc));
Point newLocation = new Point(1, y + 2);
calls++;
ScanPixelsLater(newLocation, img); //rescan the image from new y axis
}
}
}
}
/// <summary>
/// Loops through the pixels based on the p parameter, if 15 white pixels are found, the location (x & y) is
/// passed to the DetectNextWhiteLine method which fixes the next line with a similar number of white pixels.
/// </summary>
/// <param name="p">The Point(x,y) at which to start scanning</param>
/// <param name="img"></param>
private void ScanPixelsLater(Point p, Bitmap img)
{
int whitePixel = 0;
for (int y = p.Y; y < img.Height; y++)
{
for (int x = p.X; x < img.Width; x++)
{
if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
{
whitePixel++;
}
else
{
whitePixel = 0;
}
if (whitePixel == 15)
{
bottomLeftc = new Point(topLeftc.X, y);
topLeftc = new Point(x - 15, y);
calls++;
DetectNextWhiteLine(topLeftc, img);
}
}
}
// only want this to execute after all the pixels within the entire img have been read
// possibly executing early.
DrawWhiteLines(img);
AppArgs aa = new AppArgs(true);
Change(this, aa); // custom event handler, fired behind form to update GUI
}
最佳答案
因此,要了解您的应用程序挂起的原因,您需要了解一点 WinForm 应用程序的工作原理。
运行 UI 的线程也有所谓的消息泵。此消息泵包含从操作系统(和其他来源)传递到所有 UI 元素的消息。他们告诉他们什么时候改变状态,什么时候重新绘制自己等等。当你有一个像你这样的长时间运行的循环时,消息泵无法处理消息。获取排队,但从未处理过,这就是应用程序“挂起”的意思。
您的应用程序不太可能永远无法恢复。你的循环最终会结束,你的 UI 会再次响应(假设我没有错过某个地方的无限循环,但我不认为我错过了)。但是,GDI+ GetPixel 方法确实非常慢,如果您的图像很大,那么这组循环将需要很长时间才能完成。您可能不得不深入研究不安全的上下文并使用 LockBits 获取指向图像内存的指针。这里有很多关于如何做到这一点的例子。
编辑:仔细查看您的代码后,您会发现它的效率相对较低。您至少有 6 级嵌套 for 循环在那里进行,因此当只需要单次扫描时,您实质上是在多次扫描图像。
图像处理是一个资源密集型过程。您需要尽可能高效地完成所有性能密集型工作。
关于c# - For 循环,应用程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4770294/