2016-11-18 8 views
0

API呼び出しを行い、コンソールにデータを返すコンソールアプリケーションがあります。C#StackOverFlow同じメソッドを再度呼び出すとループ中の例外が発生する

私はスレッドを使用してAPIを呼び出し、メソッドを呼び出して最後に自分自身を呼び出すメッセージを取得しています。この例ではStackOverFlowExceptionがスローされます。しかし、単純なwhileループを使用しているのであれば、完璧に動作します。

最初のコードでStackOverFlowExceptionをスローする理由は、実際には2つの異なるメソッドが同じ作業をしますか?

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

Googleの "無限ループ" –

+0

申し訳ありませんが、多分質問をする前に、デバッガでコードをステップ実行する必要があります。あなたは人々にあなたを助けるために時間をとるように求めています。あなたが少なくとも何をすることができます何が間違っている自分自身を把握しようとする時間がかかります。 – Sefe

答えて

4

メソッドは、自身の呼び出しを含むすべての操作が完了するまで終了しません。メソッドがそれ自身を呼び出すたびに、現在の状態をスタックにプッシュするので、それが戻ったときに状態を復元することができます。

これを頻繁に行うと、スタックがオーバーフローします。

コードを無期限に繰り返すには、代わりにループwhile(true)を使用します。

PS。 IL has a "tail" methodあなたのコードが行うことを期待していることを実行します。現在のメソッドを完了して別のメソッドを実行しますが、C#言語には含まれていません。

+0

テールオペコード用Upvote – taffer

+2

実際には、いくつかの状況でryujitがTCOを実行します(SO人が見つけた実装には面白いバグがありました)。そのため、正しいオプションで実行すると、コードは実際には同じ動作をすることができます(私はtcoがリリースでのみ行われていると仮定しています)。 – Voo

0

この問題。

private static void GetMessagesInternal() //WORKS FINE 
{ 

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

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

これは)メソッドを使用すると、一定の条件で、このループを打破する必要が無限の時間と呼ばれます(不定loop.andのそして、getMessagesになります。

+0

ええと、彼はうまくいくと言います。彼が他のコードスニペットで持っている問題。 – RvdK

+0

MyProgram.GetMessages()と同じくらい無限の数の実行が期待されていましたが、このメソッドは無限の時間を呼び出し、BTWは問題なく動作します。 – Cool7

0

両方のスニペットの違いは入れ子です。あなた自身に電話をかけると、他の通話が終了するまで「終了」しません。

を可視化:

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

これはスタックをフラッディングします、すべての呼び出しは、スタック上に残って

そして、他の1:

-->GetMessagesInternal 
-->GetMessagesInternal 
-->GetMessagesInternal 
-->GetMessagesInternal 
-->etc 
関連する問題