如何用NetworkStream正确处理传入的protobuf消息

本文关键字:protobuf 消息 何用 NetworkStream 正确处理 | 更新日期: 2023-09-27 18:17:16

使用TCPClient的NetworkStream和protobuf-net我通过TCP发送和接收protobuf消息。接收通过以下方法完成,该方法在自己的线程中运行:

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对象仍然保存在记忆中。大消息导致系统。一段时间后OutOfMemoryExceptions .

在睡眠前显式调用GC.Collect()可以修复此问题。但它显然会减慢一切。我该如何正确处理?

如何用NetworkStream正确处理传入的protobuf消息

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
    }
}