9

Używamy EWS Managed API, który odpytuje MS Exchange dla nowych wiadomości e-mail po upływie określonego czasu. Przy każdym wywołaniu wywołania odpytywania (PullSubscription.GetEvents()) - interfejs API firmy Microsoft nie może prawidłowo usunąć wartości NetworkStream i powoduje proporcjonalne zwiększenie pamięci. To było wcześniej discussed here, ale nigdy nie rozwiązane. Za pomocą ANTS Profiler byliśmy w stanie określić, które obiekty stale rosną w pamięci i izolować problem.Jak wymusić wyrzucenie śmieci z obiektu, którego nie można usunąć?

Teraz, gdy problem został wyizolowany - czy istnieje sposób na pozbycie się obiektu NetworkStream utworzonego w zewnętrznym interfejsie API, do którego nie mamy odniesienia? GC.Collect() nie wydaje się go usuwać, ponieważ wciąż ma aktywne odniesienie. Co możemy zrobić, aby oczyścić zwisające referencje? Czy istnieje jakieś opakowanie, którego możemy użyć do wymuszenia czyszczenia ich wadliwego zestawu SDK?

+0

Zastanawiam się - czy można uzyskać referencję za pomocą odbicia? –

+0

Czy możesz napisać, gdzie znalazłeś osieroconego NetworkStream w bibliotece? Właśnie grałem w GetEventsMethod, ale nie znalazłem NetworkStream. –

+0

@HenningKrause Podałem również podejście Darena Thomasa, ale jego odbicie wymagałoby głębszego zbadania wewnętrznych cech klas ExchangeService i SubscriptionBase, które zdecydowałem się pominąć. Obecnie podążałem za numerem 1 Salvatore i otworzyłem bilet ze stwardnieniem rozsianym. Zobaczymy, co będzie dalej ... – SliverNinja

Odpowiedz

6

Nie ma sposobu, aby zmusić GC do zwolnienia pamięci dla obiektu odniesienia!

Przede wszystkim sugeruję skontaktowanie się z samym Microsoft w celu uzyskania pomocy dotyczącej tego błędu.

Po drugie, czy mówisz o "utylizacji" lub po prostu zwolnieniu pamięci? Są to dwie zupełnie różne rzeczy. (IDisposable pattern, finalizers).

Po trzecie, czy można po prostu usunąć obiekt, do którego odwołuje się te obiekty?

Po czwarte, jednym z możliwych rozwiązań może być dekompilacja za pomocą reflektora kodu, który daje problem, zrozumienie, w jaki sposób można dotrzeć do pól, które przechowują przywoływane obiekty, użyj odbicia w kodzie, aby uzyskać dostęp do pól prywatnych i ustaw je na zero. To bardzo brudny hack, ale jeśli nie masz innego sposobu, to jedyna rzecz, jaką mogę wymyślić. Zrób to tylko wtedy, gdy nie możesz podążać w jakikolwiek inny sposób.

+0

Twój brudny hack w 4 działałby, nawet jeśli pole nie jest statyczne. Zakładając, że istnieje jakiś obiekt, który nie powinien być "nieskonferencyjny", ale to (prawdopodobnie pośrednio) utrzymuje przy życiu przedmioty problemowe. – svick

+0

Tak, oczywiście, ta metoda działa w każdych okolicznościach, ale jeśli możesz po prostu usunąć obiekt, który nie odwołuje się do innego obiektu i możesz to zrobić, oczywiście, bez żadnego brudnego hacka. –

0

Najprostszym sposobem byłoby uruchomienie części, która łączy SDK z własnym AppDomain, a po zakończeniu rozładowywania AppDomain. Spowoduje to zwolnienie całej pamięci przydzielonej w AppDomain.

Musisz jednak dodać trochę pracy do projektu, ponieważ możesz wymieniać tylko z obiektem AppDomain obiekt MarshalByRef lub oznaczony jako serilizable.

Pozwoli to również monitorować ilość pamięci zużywanej przez AppDomain. Możesz więc utworzyć swoją AppDomain, uruchomić pakiet SDK, a jeśli osiągnie specjalny limit zużycia pamięci, możesz go zwolnić.