Это мой первый вопрос, и я надеюсь, что вы мне поможете.
У меня есть 2 программы, сервер и клиент, и моя проблема в клиенте.
После 2 или 3дни работы он использует более 300 МБ ОЗУ (я могу сказать это, увидев 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 сообщает мне, что у меня есть тысячи живых экземпляров byte[]
.(потому что я всегда создаю новые экземпляры ObjectState
)
Первое, что я хотел сделать: избавиться от всех ObjectState
, которые я создаю после вызова BeginReceive
, но я получаю только первое сообщение.
Тогда я хотел прекратить использовать 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 секунд, независимо от того, действительно ли я получаю данные, и это тоже не хорошо.
Так что мойвопрос в том, что я могу сделать, чтобы уменьшить использование такого большого количества оперативной памяти?Надеюсь, это хорошо объясняет мою проблему.
РЕДАКТИРОВАТЬ: Я загрузил эти изображения, надеюсь, они тоже могут быть полезны.