I'm making a Windows Form Application with VS 2010. I've added a ProgressBar to my form, and I change its value. However, the ProgressBar does not advance or change. I think one of the reasons is because the process is too fast, but I made it slow and it didn't work either.
Here's the code:
void pn_TenPercentProgressEvent(object sender, PrimeNumberEventArgs e)
{
probarPrimeNumber.Visible = true;
probarPrimeNumber.Value = (int)e.Percent * 100;
this.Refresh();
}
this is the class that event occurs:
public ulong[] Generate(int count)
{
ulong[] ulngaryResult = new ulong[count];
switch (count)
{
case 0:
{
throw new Exception("The Zero is NOT Permitted.");
}
case 1:
{
ulngaryResult[0] = 2;
break;
}
case 2:
{
ulngaryResult[1] = 3;
goto case 1;
}
default:
{
int intIndex = 0;
double dblPercent = 0.1;
for (ulong i = 2; i < ulong.MaxValue; i++)
{
if (this.IsPrime(i))
{
ulngaryResult[intIndex] = i;
intIndex++;
}
if (intIndex == (int)(dblPercent * count))
{
//Raise TenPercentProgressEvent
if (TenPercentProgressEvent != null) //Optional Event
{
TenPercentProgressEvent((object)this, new PrimeNumberEventArgs(intIndex, count, dblPercent));
}
dblPercent += 0.1;
}
if (intIndex == count)
{
//Raise FinishedProgressEvent
if (FinishedProgressEvent != null) //Optional Event
{
FinishedProgressEvent((object)this, new PrimeNumberEventArgs(intIndex, count, dblPercent));
}
break;
}
}
break;
}
}
return ulngaryResult;
}
Try (int)(e.Percent * 100). As it is, casting to int before multiplying by 100 rounds to either 0 or 1 - which then translates into either 0% or 100%, all the time, but never in between.
Related
Together with a friend, we are trying to create a sea battle for playing on a local network, we made a field of buttons, created islands on it, you can set up ships and move them. But when we connected the form to our server, after requesting the package, the form stops drawing buttons, they store the correct data, but their visual update does not occur
Here are the pieces of code
private void button1_Click(object sender, EventArgs e)
{
comboBox1.Visible = false;
comboBox2.Visible = false;
button1.Visible = false;
comboBox3.Visible = false;
button2.Visible = true;
SendPacket(PacketInfo.SendGameInfo);
Thread thread = new Thread(FightIsDone);
thread.Start();
State = GameState.Waiting;
}
void FightIsDone()
{
ReceivePacket();
this.Invoke(new Action(() => GameUpdate()));
}
public void GameUpdate()
{
Console.WriteLine("!");
State = GameState.Planing;
foreach (Ship ship in Ships)
{
ship.UseModuls();
}
SetShip(Ships);
UpdateSight();
Draw();
}
The problem is here, this method changes the image of the button or its color, it works fine until the packet is sent to the server, but after receiving it, only the information is updated, and the appearance of the form does not change
public void Draw()
{
foreach (CellButton Butt in Field)
{
if (Butt.Sigth)
{
Butt.Image = null;
SetImage(Butt);
}
else
{
Butt.BackColor = Color.Gray;
Butt.Image = null;
}
}
}
public void SetImage(CellButton Butt)
{
switch (Butt.Entety)
{
case GameObject.Water: Butt.BackColor = Color.DodgerBlue; break;
case GameObject.Island: Butt.Image = GetObjectImage(GameObject.Island); break;
case GameObject.Ship:
{
Butt.Image = Butt.modul.ModulImage;
break;
}
case GameObject.Torpedo: Butt.BackColor = Color.DarkBlue; break;
case GameObject.Fire: Butt.Image = GetObjectImage(GameObject.Fire); break;
}
}
static void SendPacket(PacketInfo info)
{
ms.Position = 0;
switch (info)
{
case PacketInfo.Connect:
writer.Write(0);
break;
case PacketInfo.SendCoordinate:
writer.Write(1);
formatter.Serialize(ms, new Coordinate(5, 0));
break;
case PacketInfo.LaunchSearch:
writer.Write(2);
writer.Write(Me.ID);
break;
case PacketInfo.SendGameInfo:
writer.Write(3);
writer.Write(Me.ID);
List<Ship> shpooks = new List<Ship>();
foreach (Ship s in Ships)
if (s.PlayerID == Me.ID) shpooks.Add(s);
formatter.Serialize(ms, shpooks);
break;
}
socket.Send(ms.GetBuffer());
}
static int ReceivePacket()
{
ms.Position = 0;
socket.Receive(ms.GetBuffer());
int code = reader.ReadInt32();
switch (code)
{
case 0:
{
Console.WriteLine("Catch");
Console.WriteLine(ms.ToString());
bool IsConected = reader.ReadBoolean();
if (IsConected)
{
Me.ID = reader.ReadInt32();
return 1;
}
break;
}
case 2:
{
return 1;
break;
}
case 3:
{
Cell[,] cells = (Cell[,])formatter.Deserialize(ms);
for (int i = 0; i < Width; i++)
for (int j = 0; j < Hight; j++)
{
Field[i, j] = new CellButton(new Coordinate(i, j));
Field[i, j].SetCell(cells[i, j]);
}
Ships.Clear();
Ships.AddRange((List<Ship>)formatter.Deserialize(ms));
break;
}
}
return -1;
}
This is the form before calling Draw():
This is how the form looks after calling Draw():
And so, after a request to the server and method Draw():
I spent a lot of time finding solutions, methods like Form.Update() and Form.Refresh() don't help
This is my code and i'm trying to do a basic calculator. Theres just one textbox where i'll be writing two numbers and adding them as well as getting the result in the same textbox like most calculators do.
my problem is that i get an error:
An unhandled exception of type 'System.StackOverflowException'
occurred in WindowsFormsApplication1.exe
after i press button + to write the next number.
public class calculator
{
int acum = 0;
int calcule(int option, int number)
{
switch (option)
{
case 3:
acum = acum + number;
break;
case 4:
acum = acum - number;
break;
case 5:
acum = acum * number;
break;
case 6:
acum = acum / number;
break;
default:
break;
}
if (number == 0)
{
return acum;
}
else
{
return calculate(option, number);
}
}
}
private void btnadd_Click(object sender, EventArgs e)
{
int numero1 = Convert.ToInt32(txtnumber.Text);
calculadora calcular = new calculadora();
txtnumber.Text = calculator.calculate(btnadd.TabIndex, number).ToString();
}
private void btnminus_Click(object sender, EventArgs e)
{
int numero1 = Convert.ToInt32(txtnumber.Text);
calculadora calcular = new calculadora();
txtnumber.Text = calculator.calculate(btnminus.TabIndex, number).ToString();
}
private void button1_Click(object sender, EventArgs e)
{
int number = Convert.ToInt32(txtnumber.Text);
calculadora calcular = new calculadora();
txtnumber.Text = calculator.calculate(button1.TabIndex, number).ToString();
}
private void button2_Click(object sender, EventArgs e)
{
int numero1 = Convert.ToInt32(txtnumber.Text);
calculadora calcular = new calculadora();
txtnumber.Text = calculator.calculate(button2.TabIndex, number).ToString();
}
First of all, there is many problems in your code:
acum is not static, each time you do Calculator calc = new Calculator(); the value is set to zero. So even if there was no error in your code, the result would be number.
The value of the arg number never changes in Calculate method so there is no way you can escape the recursive call once you enter the else here (=> StackOverflowException)
if (number == 0)
{
return acum;
}
else
{
return calculate(option, number);
}
And also Calculate(...) is private... you cannot access it outside the class Calculator
Try this :
enum OperationEnum
{
ADD=3,
SUB=4,
MUL=5,
DIV=6
}
public class Calculator
{
public double Calculate(OperationEnum operation, params int[] operands)
{
if (operands == null)
throw new InvalidOperationException();
if (operands.Length == 0)
return 0;
if (operands.Length == 1)
return operands[0];
switch (operation)
{
case OperationEnum.ADD:
return Add(operands);
case OperationEnum.SUB:
return Subtract(operands);
case OperationEnum.MUL:
return Multiply(operands);
case OperationEnum.DIV:
return Divide(operands);
default:
throw new ArgumentException("operation");
}
}
private double Divide(int[] operands)
{
if (operands.Length == 0)
return 0;
var result = operands[0];
for (int i = 1; i < operands.Length; i++)
{
double divider = operands[i];
if (divider == 0)
{
throw new DivideByZeroException();
}
result /= divider;
}
return result;
}
private double Multiply(int[] operands)
{
if (operands.Length == 0)
return 0;
double result = operands[0];
for (int i = 1; i < operands.Length; i++)
{
result *= operands[i];
}
return result;
}
private double Subtract(int[] operands)
{
if (operands.Length == 0)
return 0;
var result = operands[0];
for (int i = 1; i < operands.Length; i++)
{
result -= operands[i];
}
return result;
}
private int Add(int[] operands)
{
return operands.Sum();
}
}
private double _accumulator = 0;
private void btnadd_Click(object sender, EventArgs e)
{
int numero1 = Convert.ToInt32(txtnumber.Text);
Calculator calcular = new Calculator();
_accumulator = calcular.Calculate(OperationEnum.ADD,_accumulator, number);
txtnumber.Text = _accumulator.ToString()
}
I'm having an issue where my C# stack will accept a pushed value but then overwrite the previously existing elements in the stack with the new value as well.
Here's a chunk of the constructor for reference:
public class MazNav //handles processing and navigation
{
private Maze m;
private static Stack<int[]> path;
private int[] currCell;
private int visCell;
private Random rng;
//constructor
public MazNav(Maze mz)
{
m = mz; //assigns this object to a maze
path = new Stack<int[]>(); //initialize the stack
currCell = m.getStart(); //starts the pathfinding at start cell
visCell = 1; //initializes the visited cells count
path.Push(currCell); //adds this cell to the stack
rng = new Random(); //initializes the randomizer
The problem occurs in the if block towards the end of this method (sorry it's still ugly; I'm in the middle of debugging and will clean this up once I have something that works :) ):
public void buildMaze()
{
//variables to represent the current cell
int[] currPos; //coordinates
int nextDir = 0; //direction towards next cell
//variables to represent the next cell
int[] nextPos; //coordinates
int backDir = 0; //holds direction towards previous cell
bool deadEnd = false; //flags true when a backtrack is required
bool outOfBounds = false; //flags true when a move would leave the array
while (visCell < m.getTotCells()) //while the number of visited cells is less than the total cells
{
if (path.Count > 0) // if there is something in the stack
{
currPos = path.Peek(); //check the current coordinates
nextPos = currPos; //movement will happen one cell at a time; setting next cell coordinates the same as current allows easy adjustment
nextDir = findNextUnv(currPos); //find the direction of the next cell to check
deadEnd = false;
outOfBounds = false;
switch (nextDir)
{
case 0: //North
if (nextPos[0] - 1 >= 0)
{
nextPos[0]--;
backDir = 2;
}
else
{
outOfBounds = true;
}
break;
case 1: //East
if (nextPos[1] + 1 < m.getCols())
{
nextPos[1]++;
backDir = 3;
}
else
{
outOfBounds = true;
}
break;
case 2: //South
if(nextPos[0] + 1 < m.getRows())
{
nextPos[0]++;
backDir = 0;
}
else
{
outOfBounds = true;
}
break;
case 3: //West
if (nextPos[1] - 1 >= 0)
{
nextPos[1]--;
backDir = 1;
}
else
{
outOfBounds = true;
}
break;
case 99: //dead end
try
{
deadEnd = true;
path.Pop();
currPos = path.Peek();
int diff;
if (currPos[0] == nextPos[0])
{
diff = currPos[1] - nextPos[1];
if (diff == -1)
{
backDir = 3;
}
else if (diff == 1)
{
backDir = 1;
}
}
else if (currPos[1] == nextPos[1])
{
diff = currPos[0] - nextPos[0];
if (diff == -1)
{
backDir = 2;
}
else if (diff == 1)
{
backDir = 0;
}
}
m.getCell(nextPos[0], nextPos[1]).setBck(backDir, true);
}
catch (Exception) { }
break;
}
if (!deadEnd && !outOfBounds)
{
m.getCell(currPos[0], currPos[1]).setWal(nextDir, false);
m.getCell(nextPos[0], nextPos[1]).setWal(backDir, false);
path.Push(nextPos);
visCell++;
}
}
}
}e
The push call is only executed once but when I watch it on the debugger, after that line runs, the count increases by 1 but every element in the stack is now identical. Has anyone come across this behavior before? Where am I going wrong?
There are a lot of bugs in your code because of the way you are treating nextPos and curPos.
In particular, this line:
nextPos = currPos;
Here you are assigning nextPos to be the same array as curPos, so if you modify one, the other one will be modified along with it. And if you push one on to the stack and then modify either one, the array on the stack will be modified along with it.
The solution I would suggest is to use an immutable data type for your positions, rather than an array (which isn't particularly well suited for coordinates anyway):
internal struct Point
{
internal int X { get; private set; }
internal int Y { get; private set; }
internal Point(int x, int y)
{
X = x;
Y = y;
}
internal Point NewX(int deltaX)
{
return new Point(X + deltaX, Y);
}
internal Point NewY(int deltaY)
{
return new Point(X, Y + deltaY);
}
}
This way, when you need to transition to a new point, you can create a new one instead of modifying an existing one:
if (nextPos.X - 1 >= 0)
{
nextPos = nextPos.NewX(-1);
backDir = 2;
}
This should help you to keep a handle on your values and keep them from overwriting each other every which way.
A C++ method returns the correct value when I use a conditional breakpoint, but an incorrect value without a breakpoint.
C# method which calls C++:
bool SetProperty(Element element, Node referencePoint, List<Materializer> materializers, List<ulong> properties)
{
// Loop over STLs
for (int i = 0; i < materializers.Count; i++)
{
Materializer materializer = materializers[i];
if (materializer.IsPointInside(referencePoint.X, referencePoint.Y, referencePoint.Z, pentalTreeDatasets[i].top))
{
element.PropertyId = properties[i];
return true;
};
}
return false;
}
C++ methods in the header file:
int CountIntersects(double x, double y, double z, PentalTreeNode ^root)
{
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(!root)
return 0;
else
{
int special = CountIntersects(x,y,z,root->special);
if (x <= root->xMax && x >= root->xMin && y <= root->yMax && y >= root->yMin)
{
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
{
return (1 + special);
}
else
return special;
}
else
{
if (y>root->yMax)
{
return (CountIntersects(x,y,z,root->top)+special);
}
else if(y<root->yMin)
{
return (CountIntersects(x,y,z,root->bottom)+special);
}
else if(x<root->xMin)
{
return (CountIntersects(x,y,z,root->left)+special);
}
else if(x>root->xMax)
{
return (CountIntersects(x,y,z,root->right)+special);
}
else
return special;
}
}
}
bool IsPointInside(double x, double y, double z, PentalTreeNode ^root)
{
int intersectionCount = 0;
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(_box->IsContainingPoint(x,y,z))
{
intersectionCount=CountIntersects(x,y,z,root);
return (intersectionCount%2!=0);
}
}
C++ methods in other header files:
bool IsRayIntersectsPoly(int nPolygonIndex, Math3d::M3d RayPoints[2], CVector3D& IntersectionPoint)
{
CMeshPolygonBase& Poly = m_PolygonArray[nPolygonIndex];
CArrayResultI Result;
int* pPolygonPoints = GetPolygonPoints(Poly, Result);
Math3d::MPlane TrianglePlane;
double Atmp[3], A;
CVector3D* pPoints[3];
pPoints[0] = &m_PointArray[*pPolygonPoints].m_Position;
for(int i = 1; i < Result.GetSize() - 1; i++)
{
pPoints[1] = &m_PointArray[*(pPolygonPoints+i)].m_Position;
pPoints[2] = &m_PointArray[*(pPolygonPoints+i+1)].m_Position;
TrianglePlane.Init(*pPoints[0], *pPoints[1], *pPoints[2]);
TrianglePlane.IntersectLine(RayPoints[0], RayPoints[1], IntersectionPoint);
A = GetTriangleArea(*pPoints[0], *pPoints[1], *pPoints[2]);
for(int j = 0; j < 3; j++)
{
Atmp[j] = GetTriangleArea(*pPoints[j], *pPoints[(j+1)%3], IntersectionPoint);
}
if( fabs(A - Atmp[0] - Atmp[1] - Atmp[2]) < 1.0e-5 ) return true;
}
return false;
};
double GetTriangleArea(CVector3D& T1, CVector3D& T2, CVector3D& T3)
{
double a, b, c, s;
a = (T1 - T2).length();
b = (T2 - T3).length();
c = (T3 - T1).length();
s = 0.5 * (a + b + c);
return( sqrt(s * (s - a)* (s - b)* (s - c)) );
}
When I start the program which calls SetProperty() within the for-loop, the results for some iterator values are wrong. When I set conditional breakpoints for critical iterator values in the for-loop and step over it, then the result is OK for that item. What may be the problem?
This is method in which I post breakpoint. For example, for critical element.Id==2393.
private void StartButton_Click(object sender, EventArgs e)
{
DateTime startTime = DateTime.Now;
List<Materializer> materializers = new List<Materializer>();
List<ulong> properties = new List<ulong>();
// Load STLs
for (int i = 0; (int)i < (this.dataGridView.RowCount - 1); i++)
{
if (dataGridView.Rows[i].Cells[1].Value != null && (string)dataGridView.Rows[i].Cells[1].Value != "")
{
Materializer materializer = new Materializer();
materializer.LoadSTLMesh(dataGridView.Rows[i].Cells[0].Value.ToString());
materializers.Add(materializer);
properties.Add((ulong)dataGridView.Rows[i].Cells[1].Tag);
}
}
CreatePentalTrees(materializers);
int processedElementCount = 0;
int changedElementCount = 0;
// Loop over elements
foreach (Element element in model.ElementsList.Values)
if ((element.Topology == 7 || element.Topology == 8) && !lockedProperties.ContainsKey(element.PropertyId)) // 3D elements only
{
Node center = this.CenterPoint(element, model.NodesList);
if (element.Id == 2393)
{
//if breakpoints thats ok, else not ok
Console.WriteLine(element.Id);
Console.WriteLine(element.PropertyId);
}
if (SetProperty(element, center, materializers, properties)) // Check for center point
{
//changedElements.Add(element.Id, true);
changedElementCount++;
}
else
{
// Check for all nodes if center point does not belong to any STL
int[] nodeOrder;
switch (element.Topology)
{
case 7:
nodeOrder = wedgeNodeOrder;
break;
case 8:
nodeOrder = brickNodeOrder;
break;
default:
throw new Exception("Unknown topology " + element.Topology.ToString());
}
for (int i = 0; i < nodeOrder.Length; i++)
{
Node node = model.NodesList[element.NodeIds[nodeOrder[i]]];
if (SetProperty(element, node, materializers, properties))
{
//changedElements.Add(element.Id, true);
changedElementCount++;
break;
}
}
}
if (++processedElementCount % 100 == 0)
{
labelTime.Text = "Changed/processed elements: " + changedElementCount.ToString() + "/" + processedElementCount.ToString();
labelTime.Refresh();
Application.DoEvents();
}
}
DateTime endTime = DateTime.Now;
labelTime.Text = "Total time: " + (endTime - startTime).TotalSeconds.ToString() + " s";
MessageBox.Show("Completed.");
SaveFileDialog saveFileDlg = new SaveFileDialog();
saveFileDlg.Title = "Save FEMAP neutral file";
saveFileDlg.Filter = "(*.neu)|*.neu";
if (saveFileDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
FemapNeutral.ExportNeu(saveFileDlg.FileName, model);
}
}
You seem to be calling a lot of methods you haven't listed, and/or the wall of code made me get lost. Adding that code won't help: reducing your problem to a simpler one that demonstrates the problem might.
However, the most likely cause of your problem, if you have unmanaged code reading managed data, is that you failed to marshal or pin the data prior to using the managed code.
Unpinned data can be moved around by the garbage collector in unexpected ways.
I'm geting a StackOverflowException. Somehow, posting here seemed appropriate.
I'm using Windows Forms in a C# application. This application is intended to run on Linux, FreeBSD and Mac-OS, so I can't use WPF, so please don't suggest it.
My guess is that I'm missing a nuance of WinForms, but I cant seem to figure out what.
The ComboBox is generated by the GUI form builder in VS 2010.
The specific lines of code that are throwing the error are here:
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//I only have one of the following two at a time. Both overflow
cbx_material_num.SelectedIndex = 0;
cbx_material_num.Text = "0";
}
Since the code is somewhat complex, here's the whole function code. 'cbx_' indicates a combo box. 'txtb_' is a text box.
private void cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
{
string obj = cbx_material_obj.Text;
string num = cbx_material_num.Text;
int selnum = 0;
int n = 0;
//do we need to recreate the numbers array?
bool cur_num_is_valid = false;
cbx_material_num.Items.Clear();
if(obj != lastobj)
{
n = m_demo.get_object_modifiers(obj);
for(int i = 0; i <= n; i++)
{
string s = i.ToString();
if(s == num && i < n) cur_num_is_valid = true;
cbx_material_num.Items.Add(s);
}
}
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//Overflow here:
cbx_material_num.SelectedIndex = 0;
}
try
{
selnum = int.Parse(num);
}
catch(Exception)
{
MessageBox.Show("Error, second select menu after 'object modifiers' must be a number, not '"+num+"'.");
cbx_material_num.Text="0";
return;
}
if(selnum >= n)
{
txtb_material_param1.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
txtb_material_param4.Text = "0";
}
else
{
MaterialFace face;
MaterialParameter parameter;
int typeid;
object paramdata;
m_demo.get_object_modifiers_material(obj, selnum, out face, out parameter, out typeid, out paramdata);
cbx_material_face.Text = face.ToString();
cbx_material_paramtype.Text = parameter.ToString();
switch(typeid)
{
case 0:
txtb_material_param1.Text = ((float)paramdata).ToString();
cbx_material_datatype.Text = "float";
goto case -1;
case 1:
float[] parsf = ((float[])paramdata);
txtb_material_param1.Text = parsf[0].ToString();
txtb_material_param2.Text = parsf[1].ToString();
txtb_material_param3.Text = parsf[2].ToString();
txtb_material_param4.Text = parsf[3].ToString();
cbx_material_datatype.Text = "float[]";
break;
case 2:
txtb_material_param1.Text = ((int)paramdata).ToString();
cbx_material_datatype.Text = "int";
goto case -1;
case 3:
int[] parsi = ((int[])paramdata);
txtb_material_param1.Text = parsi[0].ToString();
txtb_material_param2.Text = parsi[1].ToString();
txtb_material_param3.Text = parsi[2].ToString();
txtb_material_param4.Text = parsi[3].ToString();
cbx_material_datatype.Text = "int[]";
break;
case -1: //can't actuall be returned, used to 'blank' the last three as '0'
txtb_material_param2.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
break;
case 4:
OpenTK.Graphics.Color4 paramc = ((OpenTK.Graphics.Color4)paramdata);
txtb_material_param1.Text = paramc.R.ToString();
txtb_material_param2.Text = paramc.G.ToString();
txtb_material_param3.Text = paramc.B.ToString();
txtb_material_param4.Text = paramc.A.ToString();
cbx_material_datatype.Text = "Color4";
break;
default: //5
Vector4 paramv = ((Vector4)paramdata);
txtb_material_param1.Text = paramv.X.ToString();
txtb_material_param2.Text = paramv.Y.ToString();
txtb_material_param3.Text = paramv.Z.ToString();
txtb_material_param4.Text = paramv.W.ToString();
cbx_material_datatype.Text = "Vector4";
break;
}
}
}
You need to check that the SelectedIndex isn't already 0 before you try to set it:
if (cbx_material_num.SelectedIndex != 0){
cbx_material_num.SelectedIndex = 0;
}
Otherwise you're re-firing the event every time through.
I think that whenever you set this cbx_material_num.SelectedIndex = 0; within the EventHandler you invoke your
cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
Each call invokes another eventHandler so the stack fills up after some time.
Basically, the fact that it is called SelectedIndexChanged doesn't mean that the value has to be different from the previous one but that the value is set through its setter.