Сборщик мусора c# не очищает память

1,00
р.
Есть статичный метод
private static bool GetXml(string date) { try { //Подключаемся к сервису KBODataProviderClient client = new KBODataProviderClient() //Получаем данные string[] result = client.getKBOContracts("2018-12-25", null)
//Если данных нет if (result == null || result.Length <= 0) { log.InfoFormat("[{0}]|Pbo return 0 rows", runGuid) return false }<br> if (File.Exists(filePath)) File.Delete(filePath)
//Сохраняем XML using (StreamWriter sw = new StreamWriter(filePath, true, Encoding.UTF8)) { //пишем первую запись с заголовков sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>") sw.WriteLine("") for (int i = 0 i < result.Length i++) { //удаляем заголовок string temp = result[i].Replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>", "") sw.WriteLine(temp) } sw.WriteLine("") }
log.InfoFormat("[{0}]|Create XML success", runGuid)
return true
} catch (Exception ex) { log.ErrorFormat("[{0}]|GetXml error {1}", runGuid, ex + Environment.NewLine + ex.StackTrace) return false } }
При вызове метода он подключается к WCF сервису, оттуда приходит массив строк (возвращает string[]), который я потом пишу в файлик. Проблема в том, что при получении данных разумеется съедается память, и после завершения метода память не очищается.
Собственно, я знаю то, что переменная string[] result является временной переменной и после завершения метода она должна собраться сборщиком мусора, но этого не происходит (данные занимают около 400мб в памяти)
Первым, что пришло в голову это проблема из-за статичного метода. Тогда я решил потереть ссылку
result = null GC.Collect()
и вызвать сборщик самому. Но и тут эффекта 0. В чем проблема?
upd:
Использование метода идет так:
if (GetXml(date)) { //парсинг }
сам метод дополнил так:
private static bool GetXml(string date) { try { //Подключаемся к сервису KBODataProviderClient client = new KBODataProviderClient() //Получаем данные string[] result = client.getKBOContracts("2018-12-25", null)
//Если данных нет if (result == null || result.Length <= 0) { log.InfoFormat("[{0}]|Pbo return 0 rows", runGuid) return false }<br> if (File.Exists(filePath)) File.Delete(filePath)
//Сохраняем XML using (StreamWriter sw = new StreamWriter(filePath, true, Encoding.UTF8)) { //пишем первую запись с заголовков sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>") sw.WriteLine("") for (int i = 0 i < result.Length i++) { //удаляем заголовок string temp = result[i].Replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>", "") sw.WriteLine(temp) } sw.WriteLine("") }
log.InfoFormat("[{0}]|Create XML success", runGuid)
client.Close() client = null
result = null
GC.Collect()
return true
} catch (Exception ex) { log.ErrorFormat("[{0}]|GetXml error {1}", runGuid, ex + Environment.NewLine + ex.StackTrace) return false } }
Клиент сервиса я закрываю и на всякий даже null присваиваю. Далее присваиваю null строке и вызываю сборщик.
В итоге при получении данных память увеличивается до 320мб(+- офк) и после завершения падает до +-211 и продолжает работать.
Метод парсинга не занимает столько памяти, т.к без получения данных при парсинге память остается на уровне +-60мб.
попробовал Array.Clear, так-же 0 эффекта (скрин выше)

Ответ
Проблема решена.
Я решил проверить все дело на левых проектах потихоньку перенося код и оказалось чудом, когда на новом проекте память очищалась нормально(требовалось лишь вызвать GC.Collect())
Первым делом я решил проверить версии .net, на проекте где все работало был 4.7.1, но изменение версии не помогло. Тогда я начал в буквальном смысле добавлять по строчке и сверять код.
Причина оказалось в app.config, а именно в секции которую генерирует VS при добавлении ссылки на сервис (там указываются таймауты и прочее). Конкретно проблема была в том, что таймауты (CloseTimeout, OpenTimeout, ReceiveTimeout, SendTimeout) указывались в привязке (секция basicHttpBinding).
Если я указывал эти таймауты в этой секции - память не очищалась (ни в основном, ни в каких других проектах), т.е если делал так:

но если я указывал таймауты через код:
client.Endpoint.Binding.CloseTimeout = new TimeSpan(0, 30, 0) client.Endpoint.Binding.OpenTimeout = new TimeSpan(0, 30, 0) client.Endpoint.Binding.ReceiveTimeout = new TimeSpan(0, 30, 0) client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 30, 0)
то сборщик мусора успешно собирал мусор.
Чтобы сделать настройку времени из конфига я воспользовался ConfigurationManager

тогда в коде я делаю так:
//Получаем время, переводим его в TimeSpan (если указать их в конфиге, то память не будет очищена) TimeSpan time = new TimeSpan(TimeSpan.TicksPerMinute * int.Parse(ConfigurationManager.AppSettings.Get("timeout"))) client.Endpoint.Binding.CloseTimeout = time client.Endpoint.Binding.OpenTimeout = time client.Endpoint.Binding.ReceiveTimeout = time client.Endpoint.Binding.SendTimeout = time
и сборщик мусора так-же успешно очищает память