.NET Remoting Singleton memory leak, TCP, Маршалл по ссылке
Я использую самый простой пример удаленного взаимодействия, который я смог найти, совместное использование объекта между службой windows и программой windows forms (клиентом), работающей на одной машине.
Служба создает экземпляр объекта следующим образом:
serviceConfigRemote = new serviceConfigDataRemote();
serverChannel = new TcpServerChannel(9090);
ChannelServices.RegisterChannel(serverChannel, false);
RemotingServices.Marshal(this.serviceConfigRemote, "ServiceConfigData");
Клиент устанавливает соединение следующим образом:
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
configData = (serviceConfigDataRemote)Activator.GetObject(typeof(serviceConfigDataRemote), "tcp://localhost:9090/ServiceConfigData");
Идея заключается в том, чтобы служба могла вносить изменения в некоторые параметры объекта, а клиент-считывать эти изменения.
Объект само по себе это:
public sealed class serviceConfigDataRemote : MarshalByRefObject
{
private bool myConnectedFlag;
private bool mySendingFlag;
private bool myUpdateFlag;
private string myClientConfiguration;
static readonly serviceConfigDataRemote instance = new serviceConfigDataRemote();
static serviceConfigDataRemote()
{
}
public serviceConfigDataRemote()
{
myConnectedFlag = false;
mySendingFlag = false;
myUpdateFlag = false;
myClientConfiguration = "";
}
public static serviceConfigDataRemote Instance
{
get
{
return instance;
}
}
public override object InitializeLifetimeService()
{
return (null);
}
public bool Connected
{
get { return myConnectedFlag; }
set { myConnectedFlag = value; }
}
public bool Sending
{
get { return mySendingFlag; }
set { mySendingFlag = value; }
}
public bool CheckForUpdates
{
get{return myUpdateFlag;}
set { myUpdateFlag = value; }
}
public string ClientConfiguration
{
get { return myClientConfiguration; }
set { myClientConfiguration = value; }
}
}
Пока служба работает сама по себе, использование Mem в Диспетчере задач остается постоянным, даже если служба постоянно обновляет объект с информацией о состоянии. Когда клиент запущен, оба начинают увеличивать использование Mem и никогда не снижаются.
Это проблема, которую я упоминал в моем предыдущем вопросе о поиске утечек памяти.
Он появляется по-разному на разных машинах, некоторые показывают отсутствие увеличения памяти, но машины, которые это делают, будут надежно воспроизводить эту проблему. Запуск .NET Memory Profiler показывает, что в службе постоянно растет число "новых экземпляров", причем только один или два "удалены" на вкладке Types/Resources, где Namespace/System-ядро, а Name/Resource-HeapMemory. Я все еще пытаюсь научиться использовать профилировщик памяти, поэтому приношу извинения, если это неверная информация, и совет о том, где еще я должен искать, также будет оценен.
Этот объект является созданный один раз, всего с парой параметров для чтения и записи, без ввода-вывода файлов, без выделения памяти, которую я могу видеть, и все же мое использование памяти, кажется, только увеличивается в тот момент, когда я запускаю соединение от клиента к этому объекту и считываю его значения. Любой и все входные данные будут оценены, так как я хотел бы избежать вытягивания этого кода и замены его именованными каналами или подобными, но я быстро приближаюсь к этому пункту как к моему единственному варианту.
3 ответа:
Не должно там, где ваш сервис создает экземпляр объекта,
serviceConfigRemote = new serviceConfigDataRemote();
Похоже на
serviceConfigRemote = serviceConfigDataRemote.Instance;
Вместо этого?
По крайней мере, так, как у вас есть, вы создаете два разных экземпляра на стороне сервера, один в статическом инициализаторе
Возможно, это и не является решением проблемы постоянно увеличивающейся памяти, но это определенно кажется чем-то вроде проблемы, требующей решения.instance
члена, который будет использоваться свойствомInstance
, а другой через явную конструкциюnew serviceConfigDataRemote()
. Также может быть полезно добавить частный конструктор к этому классу, чтобы ничто другое не могло создать экземпляр синглтона, кроме статического инициализатор.Правка:
Вот еще пара советов, которые я нашел, прочесывая сети:
- добавьте
[MTAThread]
к основному методу службы хоста.RemotingServices.Disconnect(this.serviceConfigRemote);
Когда вы отключаете службу хоста.Надеюсь, что это может помочь.
Вы пытались использовать "ленивое" создание экземпляра на ваш Синглтон. Возможно, ему не нравится, как вы его создаете.
public sealed class serviceConfigDataRemote : MarshalByRefObject { private bool myConnectedFlag; private bool mySendingFlag; private bool myUpdateFlag; private string myClientConfiguration; static serviceConfigDataRemote instance; static serviceConfigDataRemote() { } public serviceConfigDataRemote() { myConnectedFlag = false; mySendingFlag = false; myUpdateFlag = false; myClientConfiguration = ""; } public static serviceConfigDataRemote Instance { get { if (instance == null) { lock (new Object()) { if (instance == null) { instance = new serviceConfigDataRemote(); } return instance; } } return instance; } } public override object InitializeLifetimeService() { return (null); } public bool Connected { get { return myConnectedFlag; } set { myConnectedFlag = value; } } public bool Sending { get { return mySendingFlag; } set { mySendingFlag = value; } } public bool CheckForUpdates { get { return myUpdateFlag; } set { myUpdateFlag = value; } } public string ClientConfiguration { get { return myClientConfiguration; } set { myClientConfiguration = value; } } }
Поскольку единственная ОС, в которой вы видите эту ошибку, - это XP, есть несколько возможных проблем.
XP имеет ограничение на входящее соединение 10 (на pro) или 5 (на home) , и это может сыграть определенную роль в проблеме.
Убедитесь, что установлены все пакеты обновления/исправления. Я знаю, что это может быть банальным и шаблонным ответом на любые проблемы, но тот факт, что эта проблема появляется только в XP, подразумевает, что она связана с ОС.
Кроме того, не уверен, как вы используете сервис, но Windows XP-это настольная ОС,а не серверная. Если вы хотите, чтобы сервис был сервером какого-то типа, вы действительно должны использовать 2000/2003/2008 и т. д., Тем более, что он имеет проблемы только на XP.