Hello i'm having a deadlock problem with the following code. It happens when i call the function getMap(). But i can't reealy see what can cause this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.Textures;
using AForge.Math.Geometry;
namespace CDIO.Library
{
public class Polygon
{
List<IntPoint> hull;
public Polygon(List<IntPoint> hull)
{
this.hull = hull;
}
public bool inPoly(int x, int y)
{
int i, j = hull.Count - 1;
bool oddNodes = false;
for (i = 0; i < hull.Count; i++)
{
if (hull[i].Y < y && hull[j].Y >= y
|| hull[j].Y < y && hull[i].Y >= y)
{
try
{
if (hull[i].X + (y - hull[i].X) / (hull[j].X - hull[i].X) * (hull[j].X - hull[i].X) < x)
{
oddNodes = !oddNodes;
}
}
catch (DivideByZeroException e)
{
if (0 < x)
{
oddNodes = !oddNodes;
}
}
}
j = i;
}
return oddNodes;
}
public Rectangle getRectangle()
{
int x = -1, y = -1, width = -1, height = -1;
foreach (IntPoint item in hull)
{
if (item.X < x || x == -1)
x = item.X;
if (item.Y < y || y == -1)
y = item.Y;
if (item.X > width || width == -1)
width = item.X;
if (item.Y > height || height == -1)
height = item.Y;
}
return new Rectangle(x, y, width-x, height-y);
}
public Point[] getMap()
{
List<Point> points = new List<Point>();
lock (hull)
{
Rectangle rect = getRectangle();
for (int x = rect.X; x <= rect.X + rect.Width; x++)
{
for (int y = rect.Y; y <= rect.Y + rect.Height; y++)
{
if (inPoly(x, y))
points.Add(new Point(x, y));
}
}
}
return points.ToArray();
}
public float calculateArea()
{
List<IntPoint> list = new List<IntPoint>();
list.AddRange(hull);
list.Add(hull[0]);
float area = 0.0f;
for (int i = 0; i < hull.Count; i++)
{
area += list[i].X * list[i + 1].Y - list[i].Y * list[i + 1].X;
}
area = area / 2;
if (area < 0)
area = area * -1;
return area;
}
}
}
EDIT:
The "using System.Threading;" was just for some debugging ealyer where we made the thead sleep a bit, i just forgot to remove it.
We added the "lock(hull)" to see if it could fix the dead lock, it diden't.
Also the program is not runed with multi threading, so that is not the problem.
I have narroed it down to the error accuring in
if (inPoly(x, y))
points.Add(new Point(x, y));
The error message
The CLR has been unable to transition
from COM context 0x1bb7b6b0 to COM
context 0x1bb7b900 for 60 seconds. The
thread that owns the destination
context/apartment is most likely
either doing a non pumping wait or
processing a very long running
operation without pumping Windows
messages. This situation generally has
a negative performance impact and may
even lead to the application becoming
non responsive or memory usage
accumulating continually over time. To
avoid this problem, all single
threaded apartment (STA) threads
should use pumping wait primitives
(such as CoWaitForMultipleHandles) and
routinely pump messages during long
running operations.
It is a Managed Debugging Assistant warning, relating to using COM servers on a thread. One of the features of COM is that it automatically handles threading for components that do not support multi-threading. It automatically marshals a method call from a background thread to the UI thread so that the component isn't used in a thread-unsafe manner. This is completely automatic, you don't write any code yourself to make this happen.
For this to work properly, the UI thread must be idle so that it can execute the method call. The warning tells you that the UI thread has not been idle for a minute, it prevents the call from completing. The most likely reason for that is that the UI thread is blocking, waiting for the thread to complete. That will never happen, it is deadlocked. Or it could just have been busy running code for that minute, never getting around to doing its normal duties, pumping the message loop. Not pumping the message loop prevents the marshaled call from completing and trips the warning.
This should be readily visible, the main window of your app should be frozen and display the "Not Responding" message in the title bar. When you use Debug + Break All, Debug + Windows + Threads and switch to the UI thread, then look at the call stack, you should see the place where the UI thread is deadlocked. Fix it by not making the UI thread wait on the thread or by avoiding using the COM component on a worker thread. If it is completely inappropriate (shouldn't be) then you can turn off the warning with Debug + Exceptions.
That's the technical explanation for the warning. The boring one is that there was a bug in the RTM version of Visual Studio 2005. Something wrong with the debugger, it tended to trip the MDA while single stepping or inspecting variables. That got fixed in Service Pack 1, be sure to download and install it if you haven't done this yet.
in this msdn article they explain why it's better to define a variable only used in the lock statement. Clearly it avoids a lot of problem of that kind.
You are locking on the instance "hull" in getMap() and then when you call getRectangle(); you are attempting to enumerate through "hull".
Related
My goal is to create 100 dots and have them take random paths, it's for a simple evolution algorythem. However, it needs a wait timer to make the pathing unique to each dot, and from my testing and viewing of the code I see no reason for that to happen. I could just leave it like it is, but I like to understand the code I write. Because there isn't any specific error or anything, I unfortunately do have to give quite a bit of code (around 200 lines with spaces and comments), I hate doing it, but it really is only the necessary files.
They should be commented pretty well, so I hope that helps at least, sorry for the inconvinience
using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
class Genetics
{
//Just a bunch of references to classes
//----------------------------------------
Dot.Class dot = new Dot.Class();
FormSetup setup = new FormSetup();
Brain.Class brain = new Brain.Class();
Watch watch = new Watch();
Population.Class Pop = new Population.Class();
Dot.Class[] Dots;
//----------------------------------------
//The main function just starts a timer, and sets up the form in FormSetup and runs the application
private static void Main(string[] args)
{
Genetics gen = new Genetics();
gen.watch.watch();
FormSetup.Start();
}
//Makes the dots before anything visual occurs
public void Form1_Load(object sender, EventArgs e)
{
Dots = Pop.Birth();
}
//Paint sets up the goal and draws and redraws the dots by following their location
//This does not fire before the birthing process is done
public void Paint(object sender, PaintEventArgs e)
{
Goal.Class goal = new Goal.Class();
Graphics G = e.Graphics;
Pen pen = new Pen(Color.Black);
//------------------------------------
//Goal
G.DrawRectangle(pen, goal.MakeGoal());
//Since this should fire as many times as tick, which fires every 50th milisecond, it should follow the dots and drawing spheres from their locations pretty alright
//Goes through the list from the birth process (Dots) and initiates the Move() method for each of them, which sets their path coordinates randomly.
// This path SHOULD be unique to every single on of them, but without a wait timer, they aren't.
for (int i = 0; i < Dots.Length; i++)
{
Dots[i].Move();
G.DrawEllipse(pen, Dots[i].Location.X, Dots[i].Location.Y, 10, 10);
// With that testing loop, I saw how that without the sleep function, every dot had the same path, however with it, each dot's path is unique.
/* for (int b = 0; b < Dots[i].Directions.Length; b++)
{
Console.WriteLine("I am dot number: " + i + " And for step number: " + b + " my coordinate is: " + Dots[i].Directions[b]);
} */
}
}
//This just asks the form to be redrawn every 50th milisecond. This event does not fire before the Birthing process is complete.
public void Tick(object sender, EventArgs e)
{
FormSetup.form1.Invalidate();
FormSetup.form1.Update();
}
}
The code above is the main code, the most likely cause for the problem is the for loop in the paint method
Below is the brain code, which is even weirder for me, more is explained in the comments, but it shouldn't really be impacted by the wait timer at all, but alas, it is.
using System;
using System.Windows;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
namespace Brain
{
//The Brain program makes a big array of directions, and then randomizes a whole path of them
public class Class
{
// Sets up the variables
Point[] Directions;
Random rand = new Random();
//The GetDirections methods sets the size of the point array, then runs the randomize method, then returns the directions
public Point[] GetDirections(int size)
{
Directions = new Point[size];
Randomize();
return Directions;
}
// Simply fills the entire Directions point array with randonmized points
//This will output the same path over and over without the sleep function, however that doesn't make too much sense for me, since this is only called a bit AFTER the sleep function, since this method is only called after load, which stores all the dots
void Randomize()
{
for (int i = 0; i < Directions.Length; i++)
{
Directions[i] = new Point(rand.Next(-5, 5), rand.Next(-5, 5));
}
}
}
}
Then there is the population code which creates a lot of dots, this is the code that actually births the collection of dots, and also contains the sleep function
using System;
using System.Windows;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
namespace Population
{
public class Class
{
//Makes a variable for the dots array
Dot.Class[] dots;
//Birth is only called once just before the form is loaded
public Dot.Class[] Birth()
{
//Sets the size of the dots array
dots = new Dot.Class[100];
//Fills out the dots array with unique Dot classes
for (int i = 0; i < dots.Length; i++)
{
dots[i] = new Dot.Class();
//This little thing that the code requires for it to semi-work, and I have no idea why...
System.Threading.Thread.Sleep(50);
}
return dots;
}
}
}
So, as you have probarbly noticed by now, the point was for each dot to have a unique coordinate path, but for some reason it won't do this without a sleep function between each iterration of the for loop, doesn't do anything if it is outside of it.
I am seriously lost here, since I have no idea what my code is doing here, while I am new to forms, it doesn't seem to be a forms problem, since it's the pure coordinates that are the issue, not how they appear on the screen.
I would be very thankful to anyone who wants to even try and help.
Added the Dot code:
public class Class
{
//Creates relevant variables for the dots
public Point Location = new Point(1370/2, 650/2);
Point Velocity = new Point(0, 0);
Point accelleration = new Point(0, 0);
bool IsDead = false;
int DistanceToGoal = 0;
public Point[] Directions;
//Some more variables, these are just used for some cheap programming tricks
bool StartupComplete = false;
int steps = 0;
//Class references
public Brain.Class brain = new Brain.Class();
Goal.Class goal = new Goal.Class();
//This is called every 50th milisecond after the load of the form. Before this Method is called, the dot won't have any coordinates
public void Move()
{
//A one-off if statement that fills the Directions array with the randomized points from the brain
if (!StartupComplete)
{
Directions = brain.GetDirections(500);
StartupComplete = true;
}
//Will only move if not marked as death
if (!IsDead)
{
//Makes sure that we aren't going further into the array than allowed to. We do not use a for loop here, because it is called every 50th milisecond
if (steps < Directions.Length)
{
//Just fills the accelleration variable with the randomized directions relevant to the current step, and then goes to the next step for the next itteration
accelleration.X = Directions[steps].X;
accelleration.Y = Directions[steps].Y;
steps++;
}
//If there are no more directions, the dot is marked as death
else
{
IsDead = true;
}
//Sets and limits the velocity
Velocity.Y += accelleration.Y;
if (Velocity.Y > 10)
Velocity.Y = 10;
if (Velocity.Y < -10)
Velocity.Y = -10;
Velocity.X += accelleration.X;
if (Velocity.X > 10)
Velocity.X = 10;
if (Velocity.X < -10)
Velocity.X = -10;
//Moves an amount equal to the velocity, then checks if the dot is out of bounds
Location.X += Velocity.X;
Location.Y += Velocity.Y;
CheckDead();
}
}
//Just checks if the dot is just about halfway outside the form size
void CheckDead()
{
if (Location.X > 1374 || Location.X < -0.4)
IsDead = true;
if (Location.Y > 654 || Location.Y < -0.4)
IsDead = true;
}
I can only guess, but it looks like an issue with Random() since it's using the clock to generate random numbers. Also it may explain why Thread.Sleep(50) helps you with random paths.
Basically, in a tight loop you get the same value lots of times. I bet that's what happens here. You should keep a single Random instance and keep using Next on the same instance.
Try to change your randomizer to use a code below:
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
I hope it helps 😊
I am using SharpDX to make a GUI interface and associated code to allow control of the mouse cursor/emulate key presses but even at idle my app uses 15%+ cpu to the point where it increases my CPU temp +10C while my app is running, here is controller update loop running in its own thread:
private void CallToChildThread()
{
Program.stateOld = controller.GetState();
while (controller.IsConnected)
{
Program.stateNew = controller.GetState();
CheckButtons();
Point cursor;
GetCursorPos(out cursor);
short tx;
short ty;
tx = Program.stateNew.Gamepad.LeftThumbX;
ty = Program.stateNew.Gamepad.LeftThumbY;
float x = cursor.X + _xRest;
float y = cursor.Y + _yRest;
float dx = 0;
float dy = 0;
// Handle dead zone
float lengthsq = tx * tx + ty * ty;
if (lengthsq > DEAD_ZONE * DEAD_ZONE)
{
float mult = speed * getMult(lengthsq, DEAD_ZONE, acceleration_factor);
dx = getDelta(tx) * mult;
dy = getDelta(ty) * mult;
}
x += dx;
_xRest = x - (int)x;
y -= dy;
_yRest = y - (int)y;
SetCursorPos((int)x, (int)y);
Program.stateOld = Program.stateNew;
}
}
CheckButtons is just a function i use to check which buttons have been pressed, I've tried running this inside the controller update thread but I cannot get the buttons to perform as expected.
the while() and GetCursorPos contribute the most towards the total cpu usage. I've tried to compare packet numbers so my app is idle when the controller isn't being used but that causes major issues with handling cursor position(it's very slow and intermittent)
Edit: I've set the thread to background and its priority to BelowNormal but that didn't improve CPU usage very much
This is a tight loop, so it's going to fully use a CPU core. Just add a Thread.Sleep(10) at the end of each iteration. Adjust the delay if it's not responsive enough, but with 10 ms it'll be polling the controller state 100 times per second, which is already a lot.
private void CallToChildThread()
{
Program.stateOld = controller.GetState();
while (controller.IsConnected)
{
// Your update logic
Thread.Sleep(10); // Adjust the delay as needed
}
}
Also, note that lowering the thread priority is not going to decrease CPU usage. It just tells your thread to yield to another if there's not enough CPU available for everybody, which obviously isn't the case.
TaW, please see my comment. My original question about multiple intermittent errors is not getting any answers and only 1 comment, perhaps it was a bit too much information for one question. So, I think it may be best to break this down into individual issues.
My primary issue is "Object is currently in use elsewhere". I've read quite a bit about this error here on stack overflow, and locking the code in question seems to be the resolution. Perhaps I'm locking it wrong, or perhaps there's some other issue, but the lock is not working for me, so I'd appreciate opinions.
My code is designed to change the color of a sample pictureBox, there are several sample pictureBoxes, the user can then decide which sample color changes to apply to their original image.
private object lockObject = new object();
private void red()
{
// declare initial variables
int xRed = 64;
// Work around for "Cross-thread operation not valid" error. This may be a VS issue, not an actual coding error.
if (trkColor.InvokeRequired)
trkColor.Invoke(new MethodInvoker(delegate { xRed = trkColor.Value; }));
else
xRed = trkColor.Value;
// Get bitmap from picturebox
Bitmap bmp = (Bitmap)pictureBox1.Image;
lock (lockObject)
{
// search through each pixel via x, y coordinates, examine and make changes. Dont let values exceed 255 or fall under 0.
for (int y = 0; y < bmp.Height; y++)
for (int x = 0; x < bmp.Width; x++)
{
Color c = bmp.GetPixel(x, y);
int myRed = c.R, myGreen = c.G, myBlue = c.B;
myRed += xRed;
if (myRed > 255)
myRed = 255;
bmp.SetPixel(x, y, Color.FromArgb(255, myRed, myGreen, myBlue));
}
// assign the new bitmap to the picturebox
pictureBox1.Image = (Bitmap)bmp;
}
}
1) I have a list of line segments (defined by their two endpoints and a width.)
2) These line segments are drawn in a panel.
3) When my mouse moves (Panel.MouseMove event), I loop over the list of line segments.
4) Foreach:
gPath.Reset();
Pen Pen = new Pen(Color.White, 20);
gPath.AddLine(P1, P2);
return gPath.IsOutlineVisible(cursorPos, Pen);
5) If I get true, then I know my cursor is hovering over the current line segment.
This works fine for about... 300 lines or so. When I reach 1,000 my program slows to a halt (profiling shows that it's caused by IsOutlineVisible). So, is there any way I could increase performance of my hit-testing algorithm? I don't know how efficient IsOutlineVisible is, so I don't want to implement any optimizations that the method already uses. Any ideas?
EDIT:
After digging into my data I noticed some of the lines were extremely large. For example:
endpoint1 = (16000, -16000)
endpoint2 = (5041448, -32868734)
(yes, one of the coordinates is in the negative tens of millions...)
I verified that hit-testing against just one such line segment is enough to bring my program to a halt, (IsOutlineVisible takes 2-3 seconds to do the test, and the test is run whenever the cursor moves...).
I should have tested this more thoroughly before posting. Thanks to all that responded (a 2d spatial index is a great suggestion if I end-up handling thousands of lines).
p.s. If anyone knows why a large line-segment is that big a problem for IsOutlineVisible, that would be great.
Try this:
public Line GetHotSpottedLine(Point mousePos){
var line = lines.Where(line =>
{
Point p1 = new Point(Math.Min(line.P1.X, line.P2.X), Math.Min(line.P1.Y, line.P2.Y));
Point p2 = new Point(Math.Max(line.P1.X, line.P2.X), Math.Max(line.P1.Y, line.P2.Y));
return mousePos.X >= p1.X && mousePos.X <= p2.X && mousePos.Y >= p1.Y && mousePos.Y <= p2.Y;
}).FirstOrDefault(line => {
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddLine(line.P1, line.P2);
//You can declare your pen outside and this pen should be used to draw your lines.
using (Pen p = new Pen(Color.Red, 20))
{
return gp.IsOutlineVisible(mousePos, p);
}
}
});
return line;
}
public class Line{
public Point P1 { get; set; }
public Point P2 { get; set; }
}
List<Line> lines = new List<Line>();
It depends on how you want to use your lines, if you want to draw them, we have to notice the performance of drawing not detecting the hovered line, yes in that case, drawing is your problem. I think we can use some Thread here. Anyway, I tested with 1000 lines and it works OK (with drawing all the lines in Form Paint) without using any thread.
IsOutlineVisible calls the Gdi+, maybe this slows it down a bit.
public bool GraphicsPath.IsOutlineVisible(PointF pt, Pen pen, Graphics graphics)
{
int num;
if (pen == null)
{
throw new ArgumentNullException("pen");
}
int status = SafeNativeMethods.Gdip.GdipIsOutlineVisiblePathPoint(new HandleRef(this, this.nativePath), pt.X, pt.Y, new HandleRef(pen, pen.NativePen), new HandleRef(graphics, (graphics != null) ? graphics.NativeGraphics : IntPtr.Zero), out num);
if (status != 0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}
return (num != 0);
}
Beside that, these hit testing do not use optimizations like building an 2d index of all graphical elements used. To improve the performance I would try to
implement hit testing yourself and iterating over all elements
maybe use a 2D index, although for < 1000 elements I hardly believe this is necessary.
Well I'm creating an application, I'm using for loops to basically read every pixel of an image looking for patterns in pixel color (simple stuff) Anyway for some reason my application simply locks up and never reverts back to normal. I've loop through the code time and time again without seeing any real problems.
The only thing I've noticed, is the for loop in ScanPixelsLater may be exiting early. I've commented the code as much as possible,
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
}
So, to understand why your application is hanging you need to know a little bit about how WinForm applications work.
The thread that your UI is running on also has what is called a message pump. This message pump contains messages that get passed from the operating system (and other sources) to all of the UI elements. They tell them when to change state, when to redraw themselves, etc. When you have a long running loop like yours the message pump cannot process messages. The get queued up, but never processed, and this is what it means for an application to 'hang'.
It is unlikely that your application will never recover. Your loop will eventually end and your UI will become responsive again (assuming I didn't miss an infinite loop somewhere, but I don't think that I did). However, the GDI+ GetPixel method is really very slow, and if your image is large at all that set of loops is going to take a long time to complete. You will likely have to delve into an unsafe context and obtain a pointer to the image's memory using LockBits. There are many examples of how to do that floating around here.
EDIT: After looking at your code a bit more closely it is also apparent that it is relatively inefficient. You have at least 6 levels of nested for loops going on there, so you are essentially scanning the image multiple times when only a single scan is needed.
Image processing is a resource intensive process. You need to be careful to do all of your performance intensive work as efficiently as possible.
migrated from my comments (now deleted)
It is properly not this which causes you trouble since it never comes to normal but you should never call GetPixel in a loop. It is incredible slow to use that. Instead you can use pointers or an pixel array Search for "getpixel slow" with google or stackoverflow and a large number of solutions come up.
Updated: I have looked a little bit on the code now... In the main code (ScanPixels) which is a nested for-loop, you call DetectNextWhiteLine which is also a nested for-loop and finally this calls ScanPixelsLater which is ALSO a nested for-loop. Now you potentially got a 6-level-deep nested for loop O(n^6) which calls an relatively expensive method (GetPixel). You should only iterate over the pixels a few times. This may be why it never stops because this is potential something like 1000^6*~100 instructions :)