Я посмотрел на ваш код (и запустил его), и я не верю, что увеличение памяти, которое вы видите, на самом деле является утечкой памяти.
Проблема, с которой вы столкнулись, заключается в том, что ваш вызывающий код (консольное приложение) по сути работает в узком цикле.
Тем не менее, ваш обработчик должен обрабатывать каждый запрос, и он дополнительно "nobbled" Thread.Sleep(10)
. Практическим результатом этого является то, что ваш обработчик не успевает за поступающими запросами, поэтому его «рабочий набор» растет и растет по мере того, как все больше запросов помещаются в очередь, ожидая обработки.
Я взял ваш код и добавил AutoResetEvent в консольное приложение, выполнив
.WaitOne()
после request.BeginGetResponse(GetResponseCallback, request);
и
.Set()
после streamReader.ReadToEnd();
Это имеет эффект синхронизации вызовов, поэтому следующий вызов не может быть выполнен до тех пор, пока первый вызов не перезвонит (и не завершится). Поведение, которое вы видите, исчезает.
Таким образом, я думаю, что это просто сбойная ситуация, а не утечка памяти вообще.
Примечание: я отслеживал память с помощью следующего метода GetResponseCallback:
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(GC.GetTotalMemory(true));
[Изменить в ответ на комментарий от Антона]
Я не предполагаю, что здесь нет никаких проблем.
Если ваш сценарий использования таков, что использование этого обработчика является реальным сценарием использования, то, очевидно, у вас есть проблема. Я хочу сказать, что это не проблема утечки памяти, а проблема емкости. Чтобы решить эту проблему, можно написать обработчик, который мог бы работать быстрее, или масштабировать до нескольких серверов и т. Д. И т. Д.
Утечка - это когда ресурсы удерживаются после того, как они закончены, увеличивая размер рабочего набора. Эти ресурсы не были «закончены», они находятся в очереди и ожидают обслуживания. Как только они будут завершены, я верю, что их выпускают правильно.
[Изменить в ответ на дальнейшие комментарии Антона]
ОК, я кое-что раскрыл! Я думаю, что это проблема Кассини, которая не возникает в IIS. Работаете ли вы с обработчиком под Cassini (веб-сервер разработки Visual Studio)?
Я тоже вижу эти дырявые экземпляры пространства имен System.Runtime.Remoting, когда я работаю только под Cassini. Я не вижу их, если я настроил обработчик для работы под IIS. Можете ли вы подтвердить, так ли это для вас?
Это напоминает мне о некоторой другой проблеме удаленного взаимодействия / Кассини, которую я видел. IIRC, имеющий экземпляр чего-то вроде IPrincipal, который должен существовать в BeginRequest модуля, а также в конце жизненного цикла модуля, должен быть производным от MarshalByRefObject в Cassini, но не от IIS. По какой-то причине кажется, что Кассини делает внутреннее напоминание, что IIS нет.