5

I've to call a function recursively. But after a moment it throws StackOverFlowException. When I used Invoke(new Action(Start)) method, it throws same exception but not in a long moment, this is shorter than the previous one.

How can I overcome this problem?

Example Code:

private void Start()
        {
            // run select query
            mysql(selectQueryString.ToString());
            msdr = mysql();
// is finished
            if (!msdr.HasRows)
            {
                this.Finish();
                return;
            }
            //  get mysql fields
            string[] mysqlFields = Common.GetFields(ref msdr);
            while (msdr.Read())
            {
                // set lastSelectID
                lastSelectID = Convert.ToInt32(msdr[idFieldName].ToString());
                // fill mssql stored procedure parameters
                for (int i = 0; i < matchTable.Count; i++)
                {
                    string valueToAdd = Common.ConvertToEqualivantString(matchTable[i].Type, matchTable[i].Value, ref msdr, ref id, matchTable[i].Parameters);
                    sql.Ekle(matchTable[i].Key, valueToAdd);
                }
                // execute adding operation
                lastInsertID = (int)sql(false);
                // update status bar
                this.UpdateStatusBar();
// update menues
                this.UpdateMenues();
                // increment id for "{id}" statement
                id++;
            }
//  close data reader
            msdr.Close();
            msdr.Dispose();
            mysql.DisposeCommand();
// increment select limit
            selectQueryString.LimitFirst += selectQueryString.LimitLast;
            // call itself until finish
            this.Start();
        }
10
  • How many recursions are you expecting? Of course you'll eventually blow the stack.. You have no condition that stops the recursions.. it continues going forever as far as I can see.. Commented Sep 2, 2013 at 22:21
  • @SimonWhitehead The terminating condition is there at the top of the method, with an early return. But the condition doesn't look like a good one to me. Edit: and I was wrong about that, mysql() returns something different thing every time. Commented Sep 2, 2013 at 22:23
  • // increment select limit selectQueryString.LimitFirst += selectQueryString.LimitLast; Commented Sep 2, 2013 at 22:25
  • 1
    Dude, for Christ's sake, use an ORM. Stop trying to reinvent the wheel. Remove all this horrible code from your code behind. Learn and use a proper architecture and design pattern such as MVC or MVVM, instead of mashing all together UI, Business Logic and Data Access. Commented Sep 2, 2013 at 22:25
  • 6
    Why are you recursing at all?!? The correct way to do this is to loop until there are no more rows, not recurse until done and hope that you have enough stack. The way to fix this is to change your recursion into an outer loop. Commented Sep 2, 2013 at 22:33

2 Answers 2

25

When the last statement in a function is the call to the function itself, you have tail-recursion. While there are languages that optimize tail-recursion to avoid a stack overflow exception, C# is not one of them.

Recursion is not a good pattern for data that can be of an arbitrary length. Simply replace recursion by a while loop:

private void Start()
{
    while(true) {
        // run select query
        mysql(selectQueryString.ToString());
        msdr = mysql();
        // is finished
        if (!msdr.HasRows)
        {
            this.Finish();
            break;
        }
        //  rest of your code..
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

+1 for mentioning that the C# compiler doesn't do tail recursion, and its relevance to this question.
Better say that C# does not guarantee that tail call will work without stack overflow. At least on x64, tail call does work. stackoverflow.com/questions/15864670/generate-tail-call-opcode
0

You must always have the breaking condition in the recursion. If you need the best sample to implement the recursion in effective way then you can follow this approach recursion example

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.