У меня есть реальное решение, и я могу объяснить, почему!
Оказывается, что LocalReport здесь использует .NET Remoting для динамического создания дочернего домена приложения и запуска отчета, чтобы избежать внутренней утечки. Затем мы замечаем, что, в конце концов, отчет освободит всю память через 10-20 минут. Для людей с большим количеством создаваемых PDF-файлов это не сработает. Однако ключевой момент здесь заключается в том, что они используют .NET Remoting. Одна из ключевых частей Remoting - это то, что называется «Лизинг». Лизинг означает, что он будет держать этот объект Marshal некоторое время, поскольку удаленное взаимодействие, как правило, дорого в установке и, вероятно, будет использоваться более одного раза. LocalReport RDLC злоупотребляет этим.
По умолчанию время лизинга составляет ... 10 минут! Кроме того, если что-то делает различные звонки, это добавляет еще 2 минуты ко времени ожидания! Таким образом, случайным образом может быть от 10 до 20 минут, в зависимости от того, как выстроены вызовы. К счастью, вы можете изменить время ожидания. К сожалению, вы можете установить это только один раз для домена приложения ... Таким образом, если вам нужно удаленное взаимодействие, отличное от создания PDF, вам, вероятно, потребуется создать другой сервис, на котором он будет работать, чтобы вы могли изменить значения по умолчанию. Для этого все, что вам нужно сделать, это запустить эти 4 строки кода при запуске:
LifetimeServices.LeaseTime = TimeSpan.FromSeconds(5);
LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(5);
LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(1);
LifetimeServices.SponsorshipTimeout = TimeSpan.FromSeconds(5);
Вы увидите, что использование памяти начнет расти, а затем через несколько секунд вы увидите, что память снова начинает работать. Мне потребовались дни с профилировщиком памяти, чтобы действительно отследить это и понять, что происходит.
Вы не можете заключить ReportViewer в оператор using (Dispose crash), но у вас должно получиться это, если вы используете LocalReport напрямую. После этого вы можете вызвать GC.Collect (), если хотите быть вдвойне уверены, что делаете все возможное, чтобы освободить эту память.
Надеюсь, это поможет!
Редактировать
По-видимому, вы должны вызывать GC.Collect (0) после генерации отчета в формате PDF, иначе может показаться, что использование памяти по какой-то причине все еще может быть высоким.