Search code examples
c#networkingstreamtcpclientnetworkstream

C# StreamReader hangs with NetworkStream


So I've been messing with this code for awhile but couldn't figure out why it doesn't work (I called the Serialize method and Deserialize on two different threads in a while(true) loop, the Serialize thread keeps sending while the Deserialize method gets stuck)

        public static void Serialize(NetworkStream stream, object obj)
        {
            StreamWriter writer = new StreamWriter(stream);
            Console.WriteLine("Start Writing");
            writer.WriteLine(Deconstructor.Deconstruct(obj));
            Console.WriteLine("Done Writing");
        }

        public static object Deserialize(NetworkStream stream)
        {
            StreamReader reader = new StreamReader(stream);
            Console.WriteLine("Start reading");
            string objGraphData = reader.ReadLine();
            Console.WriteLine("Done reading");
            return Constructor.Construct(objGraphData);
        }

OutPut:

Accepting new socket!
Start reading
Start Writing
Done Writing
Start Writing
Done Writing
Start Writing
Done Writing
Start Writing
Done Writing
Start Writing
Done Writing
Start Writing
Done Writing
Start Writing
Done Writing

Note: The streams work as well (I've tested them before with a BinaryFormatter) but now when I use StreamWriter/StreamReader instead of a BinaryFormatter the StreamReader part hangs on the reader.ReadLine() part


Solution

  • The biggest problem here appears to be that you have a StreamReader (and writer) that is local to a single deserialize (or serialize) call. However, StreamReader and StreamWriter are stateful types that have their own local buffers (because you can't push data back into a Stream if you've read too much, and you don't want to read individual byte values, for performance reasons - so it reads a chunk and then decodes it over multiple calls).

    Because of this, once you've created a reader/writer over a Stream, you need to consider that reader/writer the single "owner" of that data. Effectively, only ever create one of each, and then don't talk directly to the stream again. Retain the reader/writer, and pass the same reader/writer to multiple successive serialize/deserialize calls.