C#StackOverFlow循环期间再次调用同一方法的异常

时间:2016-11-18 10:08:46

标签: c# multithreading exception

我有一个控制台应用程序,它进行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}");
       }
    }
}

3 个答案:

答案 0 :(得分:4)

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

经常这样做,你会溢出堆栈。

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

PS。 IL has a "tail" method执行您希望代码执行的操作 - 完成当前方法并执行另一个 - 但它不包含在C#语言中。

答案 1 :(得分:0)

这个问题。

Exception in thread "main" java.net.BindException: Address already in use: Cannot bind
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:84)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:93)
at java.net.DatagramSocket.bind(DatagramSocket.java:392)
at java.net.DatagramSocket.<init>(DatagramSocket.java:242)
at java.net.DatagramSocket.<init>(DatagramSocket.java:299)
at java.net.DatagramSocket.<init>(DatagramSocket.java:271)
at ChatBox.Client.<init>(Client.java:44)
at ChatBox.Client.main(Client.java:140)
C:\Users\HP\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53:          Java returned: 1
BUILD FAILED (total time: 0 seconds)

这将进入无限循环。并且GetMessages()方法将被调用无限时间,您需要在特定条件下断开此循环。

答案 2 :(得分:0)

两个片段之间的区别在于嵌套。如果您打电话给自己,在其他通话完成之前,您不会“退出”。

可视化:

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

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

另一个:

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