2013-06-06 1 views
1

Использование NetworkStream TCPClient и protobuf-net Я отправляю и получаю сообщения protobuf через TCP. Прием осуществляется с помощью следующего метода, который работает в отдельном потоке:Как правильно обрабатывать входящее сообщение protobuf с помощью NetworkStream?

private void HandleClientComm() 
{ 
    using (NetworkStream stream = m_Stream) 
    { 
     object o; 
     while (true) 
     { 
      if (stream.CanRead && stream.DataAvailable) 
      { 
       o = null; 
       if (Serializer.NonGeneric.TryDeserializeWithLengthPrefix(stream, PrefixStyle.Base128, Utilities.CommunicationHelper.resolver, out o)) 
       { 
        if (o != null) 
        { 
         //Do something with the incoming protobuf object 
        } 
       } 
       Thread.Sleep(1); 
      } 
     } 
    } 
} 

Это прекрасно работает, но у меня есть проблема с сборщика мусора. Похоже, что старые объекты protobuf все еще хранятся в памяти. Большое сообщение приводит к System.OutOfMemoryExceptions через некоторое время.

Явное вызов GC.Collect() перед сном устраняет эту проблему. Но это, очевидно, замедляет все. Как я могу справиться с этим правильно?

ответ

1

protobuf-net сам по себе не собирается хранить старые сообщения - действительно, если он был, то это не помогло бы GC.Collect.

Первое, что я вижу, это то, что горячая линия ожидания на DataAvailable равна действительно дорогой; что могло бы мешать GC. Вторая вещь, которую я вижу, это то, что вы, вероятно, можете освободить объект по адресу oдо спать; как случайная вещь, чтобы попытаться, возможно:

using (NetworkStream stream = m_Stream) 
{ 
    object o; 
    while (Serializer.NonGeneric.TryDeserializeWithLengthPrefix(
     stream, PrefixStyle.Base128, 
     Utilities.CommunicationHelper.resolver, out o)) 
    { 
     if (o != null) 
     { 
      //TODO: Do something with the incoming protobuf object 

      // clear o, just to give GC the very best chance while we sleep 
      o = null; 
     } 
     Thread.Sleep(1); // <=== not sure why you want to sleep here, btw 
    } 
}