9

Estamos utilizando EWS Managed API que sondea MS Exchange para nuevos mensajes de correo después de un intervalo determinado. Con cada invocación de la llamada de sondeo (PullSubscription.GetEvents()), la API de Microsoft está fallando al eliminar correctamente el NetworkStream y hace que la memoria aumente proporcionalmente. Esto fue anteriormente discussed here, pero nunca se resolvió. Utilizando ANTS Profiler pudimos determinar qué objetos crecían continuamente en la memoria y aislar el problema.¿Cómo forzar la recolección de basura del objeto que no puede desreferenciar?

Ahora que se ha aislado el problema, ¿hay alguna manera de deshacerse de un NetworkStream creado en una API externa al que no tenemos referencia? GC.Collect() no parece disponer de él ya que todavía tiene una referencia activa. ¿Qué podemos hacer para limpiar la referencia colgante? ¿Hay algún contenedor que podamos usar para forzar la limpieza de su buggy SDK?

+0

Me pregunto: ¿puede obtener la referencia a través de la reflexión? –

+0

¿Puede publicar dónde encontró el NetworkStream huérfano en la biblioteca? Acabo de hurgar en GetEventsMethod, pero no encontré un NetworkStream. –

+0

@HenningKrause También intenté con el enfoque de Daren Thomas, pero para reflejarlo necesitaría una investigación más profunda sobre las partes internas de la clase ExchangeService y SubscriptionBase que elegí omitir. Actualmente seguí el # 1 de Salvatore por ahora y abrí un boleto con MS. Veremos qué sucede después ... – SliverNinja

Respuesta

6

¡No hay forma de obligar a GC a liberar memoria para un objeto al que se hace referencia!

En primer lugar, le sugiero que se ponga en contacto con Microsoft para obtener ayuda con este error.

En segundo lugar, ¿está hablando de "eliminación" o simplemente liberación de memoria? Son dos cosas totalmente diferentes. (Patrón IDisposable, finalizadores).

En tercer lugar, ¿puede desreferenciar el objeto que hace referencia a estos objetos?

En cuarto lugar, una posible solución puede ser descompilar con reflector el código que le está dando el problema, comprender una forma de llegar a los campos que mantienen los objetos referenciados, usar la reflexión en el código para acceder a los campos privados y ponerlos a nulo. Es un truco muy sucio, pero si no tienes otro camino es lo único que se me ocurre. Haz esto solo si no puedes ir de otras maneras.

+0

Su truco sucio en 4 funcionaría incluso si el campo no es estático. Eso supone que hay algún objeto que no debe ser "sin referencia", pero que (probablemente indirectamente) mantiene vivos los objetos problemáticos. – svick

+0

Sí, por supuesto, este método funciona en todas las circunstancias, pero si solo puede desreferenciar un objeto que no está desreferenciando a otro objeto y puede hacerlo, sugeriría esto, por supuesto, sin ningún truco sucio. –

0

La manera más fácil sería ejecutar la parte que está interconectando el SDK en su propio AppDomain y después de que termine de descargar el AppDomain. Esto hará que se libere toda la memoria asignada en AppDomain.

Pero necesitará agregar algo de trabajo a su proyecto ya que solo puede intercambiar con un AppDomain el objeto MarshalByRef o marcarse como serilizable.

Esto también le permitirá controlar la cantidad de memoria consumida por el AppDomain. Para que pueda crear su AppDomain, ejecute el SDK defectuoso y, si alcanza un límite especial de consumo de memoria, puede descargarlo.

Cuestiones relacionadas