2012-01-05 8 views
1

「Good Book」によれば、非同期プログラミングモデルを実装すると、スタックオーバーフローを引き起こす行内で何度も同期して呼び出される可能性が常にあります。問題は、私はこの状況を再現することに近づくことさえできないということです。下記のプログラムでも、tcpで大量のメッセージを送信し、一度に1バイトずつ読み込みます.1回の数十回の実行で再帰が数レベルにしかなりません。APMでスタックオーバーフローを防ぐため

これは本当に問題ですか?それとも、それは単に大規模なパターンに2つの余分なメソッドを追加するだけで怖いですか?実際には、BeginMethodをコールバックが同じスレッドで実行されたときに直接呼び出すのではなく、スレッドプールのキューに入れるのはなぜですか?

using System; 
using System.Linq; 
using System.Net.Sockets; 
using System.Net; 

class Program { 
    static byte[] buff = new byte[1]; 
    static int cntr = 0; 
    static void Main(string[] args) { 
     var listener = new TcpListener(IPAddress.Loopback, 11111); 
     listener.Start(); 
     new Action(() => { 
      byte[] message = Enumerable.Range(0, 100000).Select(i => (byte)i).ToArray(); 
      var client = new TcpClient(); 
      client.Connect(IPAddress.Loopback, 11111); 
      using (var s = client.GetStream()) s.Write(message, 0, message.Length); 
     }).BeginInvoke(null, null); 
     var stream = listener.AcceptTcpClient().GetStream(); 
     stream.BeginRead(buff, 0, buff.Length, callback, stream); 
     Console.ReadLine(); 
    } 
    static void callback(IAsyncResult iar) { 
     if (iar.CompletedSynchronously) Console.Write(cntr++ +" "); else cntr=0; 
     var stream = iar.AsyncState as NetworkStream; 
     if (stream.EndRead(iar) > 0) { 
      stream.BeginRead(buff, 0, buff.Length, callback, stream); 
     } 
    } 
} 

答えて

0

1つのスレッドのスタックにあまりにも多くのオブジェクトを配置すると、スタックオーバーフローが発生することがあります。非同期new Action(..).BeginInvoke()または実際には任意のデリゲートBeginInvokefrom thread pool利用可能なスレッドを使用するため、任意の新しい非同期呼び出しのどちらかになります。利用可能
またはを(それを使用して、プールに戻り)場合

  • は、プールから新しいスレッドを取りますあなたはSOの例外を再現したいのであれば、あなたは一つのスレッドだけをロードすることを確認してください返さまたはそれに加えて

を作成するスレッドの

  • 待ちます。 BTW、byte[] messageは、管理されたヒープに格納されます。

  • +0

    非同期呼び出しは、そのジョブを同期して完了させることができ、スレッドプールをまったく使用しませんが、タスクが非常に迅速に終了できる場合にのみ使用できます。ソケットから1バイトを読み取ることは、私が思い付くことができる最も小さい実生活の仕事です。 – user1096188

    関連する問題