通过再次调用相同的方法,循环期间出现C#StackOverFlow异常

通过再次调用相同的方法,循环期间出现C#StackOverFlow异常,c#,multithreading,exception,C#,Multithreading,Exception,我有一个控制台应用程序,它进行API调用并将数据返回控制台 我正在使用线程开始调用API并调用方法来获取最终调用自身的消息。此示例抛出StackOverFlowException。但如果我使用简单的while循环,它的工作就完美了 为什么它在第一个代码示例中抛出StackOverFlowException,然后两个不同的方法实际执行相同的工作 var thread = new Thread(GetMessagesInternal); thread.Start(); private static

我有一个控制台应用程序,它进行API调用并将数据返回控制台

我正在使用线程开始调用API并调用方法来获取最终调用自身的消息。此示例抛出StackOverFlowException。但如果我使用简单的while循环,它的工作就完美了

为什么它在第一个代码示例中抛出StackOverFlowException,然后两个不同的方法实际执行相同的工作

var thread = new Thread(GetMessagesInternal);
thread.Start();

private static void GetMessagesInternal() { //THROWS STACKOVERFLOWEXCEPTION

    var messages = MyProgram.GetMessages();

    foreach (var message in messages) {
        Console.WriteLine($"{message.MessageText}");
    }

    GetMessagesInternal();
}

    private static void GetMessagesInternal() { //WORKS FINE

    while(true) {

       var messages = MyProgram.GetMessages();

       foreach (var message in messages) {
           Console.WriteLine($"{message.MessageText}");
       }
    }
}

方法在完成所有操作(包括对自身的调用)之前不会完成。每次方法调用自身时,它都会将当前状态推送到堆栈上,因此当它返回时,可以恢复其状态

这样做太频繁,会使堆栈溢出

要无限期地重复代码,您可以改为在
while(true)
循环中重复代码


注:这就是您希望代码执行的操作—完成当前方法并执行另一个方法—但它不包含在C语言中。

方法只有完成所有操作(包括对自身的调用)后才能完成。每次方法调用自身时,它都会将当前状态推送到堆栈上,因此当它返回时,可以恢复其状态

这样做太频繁,会使堆栈溢出

要无限期地重复代码,您可以改为在
while(true)
循环中重复代码


注:这就是您希望代码执行的操作——完成当前方法并执行另一个方法——但C语言中不包含它。

这是一个问题

    private static void GetMessagesInternal() //WORKS FINE
{

    while(true)
    {
       var messages = MyProgram.GetMessages();

       foreach (var message in messages)
       {
           Console.WriteLine($"{message.MessageText}");
        }
    }

这将在无限循环中进行。并且GetMessages()方法将在需要在特定条件下中断此循环的无限时间内被调用。

此方法的问题

    private static void GetMessagesInternal() //WORKS FINE
{

    while(true)
    {
       var messages = MyProgram.GetMessages();

       foreach (var message in messages)
       {
           Console.WriteLine($"{message.MessageText}");
        }
    }

这将进入无限循环。如果在特定条件下需要中断此循环,则GetMessages()方法将在无限时间内被调用。

这两个代码段之间的区别在于嵌套。如果你给自己打电话,在另一个电话结束之前,你不会“退出”

可视化:

-->GetMessagesInternal
    --> GetMessagesInternal
        --> GetMessagesInternal
            --> GetMessagesInternal
                --> etc
这将淹没堆栈,每个调用都保留在堆栈上

另一个:

-->GetMessagesInternal
-->GetMessagesInternal
-->GetMessagesInternal
-->GetMessagesInternal
-->etc

两个代码段之间的区别在于嵌套。如果你给自己打电话,在另一个电话结束之前,你不会“退出”

可视化:

-->GetMessagesInternal
    --> GetMessagesInternal
        --> GetMessagesInternal
            --> GetMessagesInternal
                --> etc
这将淹没堆栈,每个调用都保留在堆栈上

另一个:

-->GetMessagesInternal
-->GetMessagesInternal
-->GetMessagesInternal
-->GetMessagesInternal
-->etc

谷歌“无限递归”很抱歉,但在你提问之前,也许你应该在调试器中逐步检查你的代码。你要求人们花时间来帮助你。你至少可以花点时间来找出自己出了什么问题。谷歌“无限递归”很抱歉,但在你提问之前,也许你应该在调试器中逐步检查你的代码。你要求人们花时间来帮助你。你至少能做的是花点时间试着弄清楚自己出了什么问题。嗯,他说这很管用。他对另一个代码片段的问题。我希望while(true)将作为MyProgram.GetMessages()得到无限数执行。这个方法将得到调用无限时间,顺便说一句,它可以工作,然后就不重要了。嗯,他说它工作得很好。他对另一个代码片段的问题。我希望while(true)将作为MyProgram获得无限次数的执行。GetMessages()此方法将获得调用无限时间,顺便说一句,它可以工作,然后就不要紧了。实际上,ryujit在某些情况下会进行TCO(SO发现在实现中甚至有一个有趣的bug)。因此,如果使用正确的选项运行,代码实际上可以表现出相同的行为(我假设tco只在发行版中完成)。实际上,ryujit在某些情况下执行tco(So人员发现的实现中甚至有一个有趣的bug)。因此,如果使用正确的选项运行,代码的行为实际上可能完全相同(我假设tco只在发行版中完成)。