Recursive method not restarting

leorob88

Well-known member
Joined
Dec 31, 2020
Messages
56
Programming Experience
1-3
I'm not understanding why and I don't find any resources explaining clearly where the issue should be, when I try to recall a method (not a function). I'm asking for specific help or code, not some general conceptual advice, I would need some actual help to understand how to achieve what I need, if I don't get a practical example I suppose I'll never understand.
I have a method following a bunch of instructions and when I reach some point I have a check/statement: if the condition is met -> restart the whole code of this method.
From what I read online it should be easy as that but it actually doesn't work.
The first approach was inside the Click event of a Button, so in the check condition part it was just
C#:
if (condition) { button1.PerformClick();
What happens is just the instruction seems to be ignored although it gets read (tried to debug with breakpoints).
I also tried with an if-else statement, like
C#:
if (condition) { button1.PerformClick(); } else { go on with the remaining part }
I also tried to use different instructions like
C#:
button1.Invoke(new Action(() => { button1.PerformClick(); }));
or
C#:
button1_Click(button1, EventArgs.Empty);
but none worked. I also tried moving the full code in a private void, so the button would call the void method and so would do the method as well, but not even that worked. Can someone give a piece of advice to understand how this works or why it doesn't? It seems total nonsense to me it's so difficult to perform such a basic instruction.
 
Are you sure it is not working? Did you set breakpoints to validate?

Separate your UI from your business logic.

Instead of doing:
C#:
void button1_Click(object sender, EventArgs e)
{
    // do some work

    if (condition)
    {
        button1.PerformClick();
    }

    // do more work
}

Do this instead:
C#:
void DoSomeWork()
{
    // do some work

    if (condition)
    {
        DoSomeWork();
    }

    // do more work
}

void button1_Click(object sender, EventArgs e)
{
    DoSomeWork();
}

In general though, most beginners think that they want a recursive call when they actually want to do multiple iterations. The only reason why they do the recursive call is because they think that they are following the rule "goto's are evil[/icode].
 
Not following my own advice about breaking out the business logic, the PerformClick() works for me:
C#:
using System;
using System.Windows.Forms;
using System.Drawing;

namespace WinForms
{
    class MainForm : Form
    {
        Button m_btnRecurse;
        int m_count = 0;

        MainForm()
        {
            m_btnRecurse = new Button()
            {
                Text = "Recurse"
            };
            m_btnRecurse.Click += btnRecurse_Click;

            Controls.Add(m_btnRecurse);
        }

        private void btnRecurse_Click(object sender, EventArgs e)
        {
            m_count++;
            Text = $"Recurse count = {m_count}";
            if (m_count < 500)
            {
                m_btnRecurse.PerformClick();
            }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}
 
Not following my own advice about breaking out the business logic, the PerformClick() works for me:
C#:
using System;
using System.Windows.Forms;
using System.Drawing;

namespace WinForms
{
    class MainForm : Form
    {
        Button m_btnRecurse;
        int m_count = 0;

        MainForm()
        {
            m_btnRecurse = new Button()
            {
                Text = "Recurse"
            };
            m_btnRecurse.Click += btnRecurse_Click;

            Controls.Add(m_btnRecurse);
        }

        private void btnRecurse_Click(object sender, EventArgs e)
        {
            m_count++;
            Text = $"Recurse count = {m_count}";
            if (m_count < 500)
            {
                m_btnRecurse.PerformClick();
            }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

So what you get is the button text becomes 500 in the end? I can confirm it doesn't work for me. I basically have an "if condition" making the "branch" of the instructions, so it's straight as that: if i'm on that condition, my conditions are wrong and I have to repeat the whole process. What the program does in runtime seems literally to read the instruction but not execute it. Meaning: I expect in that moment the next instruction executed will be the first instruction of the whole block, like a full restart. But it doesn't, it proceeds reading the next instruction below.
 
Not following my own advice about breaking out the business logic, the PerformClick() works for me:
C#:
using System;
using System.Windows.Forms;
using System.Drawing;

namespace WinForms
{
    class MainForm : Form
    {
        Button m_btnRecurse;
        int m_count = 0;

        MainForm()
        {
            m_btnRecurse = new Button()
            {
                Text = "Recurse"
            };
            m_btnRecurse.Click += btnRecurse_Click;

            Controls.Add(m_btnRecurse);
        }

        private void btnRecurse_Click(object sender, EventArgs e)
        {
            m_count++;
            Text = $"Recurse count = {m_count}";
            if (m_count < 500)
            {
                m_btnRecurse.PerformClick();
            }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

C#:
//making an exapmle of my code although it's different it has the same structure

private void button1_click(.....)
{
    //1.start
    //do stuff, variables, instructions and other
    //2.
    if (classObj1.stringProperty == "ThisText" && classObj2.stringProperty == "ThisText")
    {
        button1.PerformClick();
    }
    //3.the rest of the instructions if the condition is not met
}
What I'm expecting is the button perform click restarts from 1. Is this wrong?
 
I literally reproduced the code in a simpler example in a new project and with minimal code instructions it works. definitely I suppose there's something in my code preventing the restart instruction from working. I'll try to debug from here...
 
I'll try to debug from here..

And truly debug. Set breakpoints. Inspect the values of the variables. Some people call "running my code and trying to see if it gives expected results" debugging. That is not debugging. That is called testing.
 
And truly debug. Set breakpoints. Inspect the values of the variables. Some people call "running my code and trying to see if it gives expected results" debugging. That is not debugging. That is called testing.

yes and no. actually i'm thinking of kinda changing approach because this doesn't make any sense. literally my code "if string 1 is X and string 2 is X, restart from the beginning", only, one program actually says "ok, the values are X, ok, so you want me to restart, ok, I'll restart", the other one says "ok, the values are X, ok, so you want me to restart, ok, I won't" and i don't understand why. I suspect there is something basic about recursion that I don't know, My real question is "what?". Crazy as that might be, the first solution that comes to my mind is instead of stating "do stuff, check condition, if condition, restart", stating "do stuff while condition is true". only, i find it ridiculous. how can a recursion be so complicated or tricky to use? as long as i know, it should be quite straightforward...
 
C#:
//making an exapmle of my code although it's different it has the same structure

private void button1_click(.....)
{
//1.start
//do stuff, variables, instructions and other
//2.
if (classObj1.stringProperty == "ThisText" && classObj2.stringProperty == "ThisText")
{
button1.PerformClick();
}
//3.the rest of the instructions if the condition is not met
}
What I'm expecting is the button perform click restarts from 1. Is this wrong?

The expectation is slightly flawed. PerformClick() is not a goto in disguise. Don't expect the debugger to suddenly take you to the top of the method. You need set a breakpoint at the top of the event handler to catch the next execution of your method.

Seeing the code behind PerformClick() might be insightful:
PerformClick():
public void PerformClick() {
    if (CanSelect) {
        bool validatedControlAllowsFocusChange;
        bool validate = ValidateActiveControl(out validatedControlAllowsFocusChange);
        if (!ValidationCancelled && (validate || validatedControlAllowsFocusChange))
        {
            //Paint in raised state...
            //
            ResetFlagsandPaint();
            OnClick(EventArgs.Empty);
        }
    }
}

from Reference Source .

Perhaps your form performs some validation and validation has failed?

On another tangent, are you sure about your condition?
Do you consider yourself as knowing English as your first language and you are American. Some Americans will use the word "and" when they actually mean "or". I've run across some examples of these in laws or rule books. Some will say that you are guilty of reckless driving because you are driving over 80 MPH on a abandoned runway, but the law as written says something like "a person shall be guilty of reckless driving if they are driving over 80 MPH; operating a vehicle in a dangerous manner; and endangering other people." The law in that state actually meant to use "or", not "and".
 
yes and no. actually i'm thinking of kinda changing approach because this doesn't make any sense. literally my code "if string 1 is X and string 2 is X, restart from the beginning", only, one program actually says "ok, the values are X, ok, so you want me to restart, ok, I'll restart", the other one says "ok, the values are X, ok, so you want me to restart, ok, I won't" and i don't understand why. I suspect there is something basic about recursion that I don't know, My real question is "what?". Crazy as that might be, the first solution that comes to my mind is instead of stating "do stuff, check condition, if condition, restart", stating "do stuff while condition is true". only, i find it ridiculous. how can a recursion be so complicated or tricky to use? as long as i know, it should be quite straightforward...

It sounds like you don't really want recursion. It sounds like you want something to iterate. Recursion is the wrong solution.
 
It sounds like you don't really want recursion. It sounds like you want something to iterate. Recursion is the wrong solution.

Not in my knowledge. Recursion is when you call a method or function inside itself and it's what I need. My button or method must do stuff and meanwhile, at some point, if certain conditions are (not) met, the whole stuff has to repeat from the start. To me, recursion is the most immediate solution you can come up with. Like you want to count some items (meaning, literally you, out loud), if you lose count at some point, you just restart from the beginning.
 
On another tangent, are you sure about your condition?
Do you consider yourself as knowing English as your first language and you are American. Some Americans will use the word "and" when they actually mean "or". I've run across some examples of these in laws or rule books. Some will say that you are guilty of reckless driving because you are driving over 80 MPH on a abandoned runway, but the law as written says something like "a person shall be guilty of reckless driving if they are driving over 80 MPH; operating a vehicle in a dangerous manner; and endangering other people." The law in that state actually meant to use "or", not "and".

I am sure of the condition and for 2 reasons: 1.the code runs the instructions inside the "if" statement and 2.i checked the values and they actually are what triggers the "if" statement. as long as I know, there's no validation (unless the only one I can think of? meaning the first instructions set to "" some text controls of the form).
 
Last edited:
The expectation is slightly flawed. PerformClick() is not a goto in disguise. Don't expect the debugger to suddenly take you to the top of the method.

Also, I could question this assumption (ish). As i said i tried another new project and actually the perform click works literally as a "goto" instruction and the next instructions below actually never get executed because the code executed is always the first part, it gets to the if -> perform click and keeps on repeating that. Aside this, if a perform click is not a "goto", what can be a "goto"? Meaning, should it work if I state a "goto" at the beginning of the button event and then I call that?
 
Last edited:
C#:
//Try this, it works, you'll never reach the MessageBox

        List<Obj> objs = new List<Obj>();
        public class Obj
        {
            public string name { get; set; }
        }
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            objs.Add(new Obj() { name = "table" });
            objs.Add(new Obj() { name = "chair" });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Obj obj1 = objs[0];
            Obj obj2 = objs[1];
            obj1.name = "nay";
            obj2.name = "nay";
            if (obj1.name == "nay" && obj2.name == "nay")
            {
                button1.PerformClick();
            }
            MessageBox.Show("ok");
        }
 
Try this, it works, you'll never reach the MessageBox
Line 29 will not be reached until previous calls are finished, and they never will. You get infinite recursion and end up with stack overflow exception.
 
Back
Top Bottom