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();
 }
asked Sep 2, 2013 at 22:20
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..
 }
}
answered Sep 3, 2013 at 0:54
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

answered Aug 30, 2023 at 18:24

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.