c# - 服务器/客户端。客户端使用大量内存

标签 c# sockets asynchronous

这是我的第一个问题,希望您能帮助我。

我有 2 个程序,一个服务器和一个客户端,我的问题出在客户端。

运行 2 或 3 天后,它使用了超过 300MB 的 RAM(我可以通过查看 TaskManager 来判断)并且从未释放它!另外,我不得不说这个客户端每秒从 GPS 设备接收数据。 我用 ANTS Memory Profiler 分析了我的客户端,我注意到我多次创建了一个对象,但它们从未被销毁。

这是我的代码:

private static TcpClient _client;
private readonly ManualResetEvent _receiveDone = new ManualResetEvent(false);

public void Receive()
{
    if (_client.Connected)
    {
        _receiveDone.Reset();
        ObjectState state = new ObjectState(); 
        state.WorkSocket = _client.Client;
        state.Data = new byte[_client.ReceiveBufferSize];
        _client.Client.BeginReceive(state.Data, 0, Convert.ToInt32(_client.ReceiveBufferSize), 0, ReceiveCallback, state);

        if (!_receiveDone.WaitOne(20000)) 
        {
            //after 20 seconds WITHOUT RECEIVING DATA, do some code to test if the connection is alive                        
        }
    }
}

void ReceiveCallback(IAsyncResult ar)
{
    ObjectState state = (ObjectState)ar.AsyncState;
    Socket client = state.WorkSocket;
    if (client.Connected)
    {
        int bytesRead = client.EndReceive(ar);
        if (bytesRead > 0)
        {
            string response = Encoding.ASCII.GetString(state.Data, 0, bytesRead);
            doProcess(response);
            client.BeginReceive(state.Data, 0, Convert.ToInt32(_client.ReceiveBufferSize), 0, ReceiveCallback, state);
            _receiveDone.Set();
        }
        else
        {
        //Disconnection
        }
    }
}

public class ObjectState
{
    public Socket WorkSocket;
    public byte[] Data;
}

ANTS Memory Profiler 告诉我我有数千个 byte[] 的事件实例。 (因为我总是创建 ObjectState 的新实例)

我想做的第一件事:处置我在调用 BeginReceive 后创建的所有 ObjectState,但我只收到第一条消息。

然后我想停止使用 ObjectState... 怎么办? 这是我修改后的代码:

private _data byte[];

public void Receive()
{
    if (_client.Connected)
    {
        _receiveDone.Reset();
        _data = new byte[_client.ReceiveBufferSize];
        _client.Client.BeginReceive(_data, 0, Convert.ToInt32(_client.ReceiveBufferSize), 0, ReceiveCallback, null);

        if (!_receiveDone.WaitOne(20000)) 
        {
            //after 20 seconds of inactivity do some code to test if the connectio is alive                        
        }
    }
}

void ReceiveCallback(IAsyncResult ar)
{
    Socket client = _cliente.Client;
    if (client.Connected)
    {
        int bytesRead = client.EndReceive(ar);
        if (bytesRead > 0)
        {
            string response = Encoding.ASCII.GetString(_data, 0, bytesRead);
            doProcess(response);
            client.BeginReceive(_data, 0, Convert.ToInt32(_client.ReceiveBufferSize), 0, ReceiveCallback, null);
            _receiveDone.Set();
        }
        else
        {
            //Disconnection
        }
    }
}

这是怎么回事?我只收到第一条消息,所以这不好。 然后,如果我删除 _receiveDone.Set 它会收到所有消息,但是 _receiveDone.WaitOne(2000) 总是每 20 秒执行一次,无论我是否真的收到数据,这也不好。

所以我的问题是,我可以做些什么来减少这么多 RAM 的使用?我希望这能很好地解释我的问题。

编辑: 我上传了这些图片,希望它们也能有所帮助。 Summary Instant Retention Graph

最佳答案

if (client.Connected)
{
    int bytesRead = client.EndReceive(ar);
    // etc..

调用 EndReceive 不是可选的,您必须调用它,否则会泄漏资源。使用 try/catch 捕获 ObjectDisposedException。

关于c# - 服务器/客户端。客户端使用大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8039340/

相关文章:

c# - 使用 rhino mock 的 lambda 单元测试失败

powershell - 如何在执行静默安装时异步运行进度条?

ios - 关于AFNetworking : how to add the response data to NSMutable Array中的异步连接

c# - 无法用两个表创建外键

c# - 通过 COM Interop 公开索引器/默认属性

c# - 将 MySQl 'YYYY-MM-DD' 转换为 .Net DateTimePicker

java - 文件传输服务器 <-> 客户端,文件不完整

sockets - TCP 套接字和 .Net Micro Framework

macos - 如何增加osx上套接字的限制以进行负载测试?

asynchronous - Rust:加入并迭代 future 结果