9

Utilizziamo API gestita da EWS che esegue il polling di MS Exchange per i nuovi messaggi di posta dopo un determinato intervallo. Ad ogni chiamata del sondaggio (PullSubscription.GetEvents()) - L'API Microsofts non riesce a disporre correttamente dello NetworkStream e fa aumentare proporzionalmente la memoria. Questo era precedentemente discussed here, ma mai risolto. Usando ANTS Profiler siamo stati in grado di determinare quali oggetti erano in continua crescita in memoria e isolare il problema.Come forzare la garbage collection di oggetti non è possibile effettuare il dereferenziamento?

Ora che il problema è stato isolato, esiste un modo per disporre di un NetworkStream creato in un'API esterna a cui non si fa riferimento? GC.Collect() non sembra disporlo poiché ha ancora un riferimento attivo. Cosa possiamo fare per ripulire il riferimento ciondolante? C'è un wrapper che possiamo usare per forzare la pulizia del loro SDK bacato?

+0

Mi chiedo: riesci a ottenere il riferimento tramite riflessione? –

+0

Puoi postare dove hai trovato il NetworkStream orfano nella libreria? Ho solo cercato il metodo GetEventsMethod, ma non ho trovato un NetworkStream. –

+0

@HenningKrause Ho anche provato l'approccio di Daren Thomas, ma riflettere implicherebbe un'indagine più approfondita sui componenti interni della classe ExchangeService e SubscriptionBase che ho scelto di saltare. Al momento ho seguito il numero 1 di Salvatore per ora e ho aperto un ticket con MS. Vedremo cosa succederà dopo ... – SliverNinja

risposta

6

Non c'è modo di forzare GC a rilasciare memoria per un oggetto referenziato!

Prima di tutto suggerirei di contattare microsoft stesso per un aiuto con questo bug.

In secondo luogo, stai parlando di "smaltimento" o solo di una versione di memoria? Sono due cose completamente diverse. (Modello identificabile, finalizzatori).

In terzo luogo, puoi semplicemente trasferire l'oggetto che fa riferimento a questi oggetti?

In quarto luogo, una soluzione possibile può essere quella di decompilare con riflettore il codice che ti sta dando il problema, capire un modo per arrivare ai campi che mantengono gli oggetti di riferimento, utilizzare la riflessione nel codice per accedere ai campi privati e metterli a zero. È un trucco molto sporco, ma se non hai altro modo è l'unica cosa a cui riesco a pensare. Fallo solo se non puoi andare in altri modi.

+0

Il tuo trucco sporco in 4 funzionerebbe anche se il campo non è statico. Ciò presuppone che ci sia qualche oggetto che non dovrebbe essere "non referenziato", ma che (probabilmente indirettamente) mantiene vivi gli oggetti problematici. – svick

+0

Sì, certo, questo metodo funziona in tutte le circostanze, ma se si può semplicemente dereferenziare un oggetto che non denota altri oggetti e lo si può fare lo consiglierei ovviamente, senza alcun trucco sporco. –

0

Il modo più semplice sarebbe eseguire la parte che interfaccia l'SDK nel proprio AppDomain e dopo aver terminato di scaricare AppDomain. Ciò causerà la liberazione di tutta la memoria allocata nell'AppDomain.

Ma è necessario aggiungere un po 'di lavoro al progetto in quanto è possibile interscambiare solo con un AppDomain un oggetto MarshalByRef o contrassegnato come serilizable.

Ciò consentirà inoltre di monitorare la quantità di memoria consumata da AppDomain. Quindi puoi creare il tuo AppDomain, eseguire l'SDK buggy e se raggiunge un limite speciale di consumo di memoria puoi scaricarlo.