【问题标题】:Recursive Function Calls Throw StackOverFlowException递归函数调用抛出 StackOverFlowException
【发布时间】:2013-09-06 01:14:28
【问题描述】:

我必须递归调用一个函数。但片刻之后它会抛出 StackOverFlowException。当我使用 Invoke(new Action(Start)) 方法时,它会抛出相同的异常,但不会很长时间,这比前一个要短。

我该如何克服这个问题?

示例代码:

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();
        }

【问题讨论】:

  • 您期望有多少次递归?当然,您最终会破坏堆栈..您没有停止递归的条件..据我所知,它会一直持续下去..
  • @SimonWhitehead 终止条件在方法的顶部,提前返回。但对我来说,情况看起来并不好。编辑:我错了,mysql() 每次都会返回不同的东西。
  • // 增加选择限制 selectQueryString.LimitFirst += selectQueryString.LimitLast;
  • 老兄,看在上帝的份上,使用 ORM。停止尝试重新发明轮子。从后面的代码中删除所有这些可怕的代码。学习并使用适当的架构和设计模式,例如 MVC 或 MVVM,而不是将 UI、业务逻辑和数据访问混合在一起。
  • 你为什么要递归?!?执行此操作的正确方法是 循环 直到没有更多行,在完成之前不递归并希望您有足够的堆栈。解决此问题的方法是将递归更改为外循环。

标签: c# .net


【解决方案1】:

当函数中的最后一条语句是对函数本身的调用时,您有 tail-recursion. 虽然有些语言会优化尾递归以避免堆栈溢出异常,但 C# 不是其中之一。

对于可以是任意长度的数据,递归不是一个好的模式。只需用 while 循环替换递归:

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..
    }
}

【讨论】:

猜你喜欢
  • 2023-03-10
  • 2013-07-11
  • 1970-01-01
  • 2015-03-02
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多