Spędziłem kilka ostatnich dni na zaglądaniu w to i nie mogę tego zrozumieć.CrystalReports ReportDocument wyciek pamięci z połączeniami z bazami danych
Mam aplikację c#
WinForms
, która używa ReportDocument
do załadowania raportu i umieszczenia go w przeglądarce Crystal Report Viewer, aby użytkownik mógł wyświetlić podgląd. Celem jest podgląd różnych statystyk, a formularz nigdy nie jest zamknięty. Jest zegar, który uruchamia się i ładuje różne raporty do przeglądarki.
Podczas gdy tak się dzieje, zużycie pamięci i obsługuje (widzę je w menedżerze zadań) nadal rośnie. Po uruchomieniu aplikacji zużywa około 30 MB, a gdy działa przez 10 minut, wykorzystuje około 200 MB i stale rośnie.
Dużo czytałem o tym problemie w Internecie i odkryłem, że zarówno ReportDocument
, jak i Viewer muszą zostać zamknięte i usunięte. Niestety to nie naprawia. Typ połączenia w raportach to OLE DB(ADO)
, ponieważ dane są pobierane z bazy danych SQL Server
.
Krótko mówiąc, Form1 ma zegar, który po upłynięciu wywołuje Crystal Reports Viewer
i wywołuje funkcję czyszczenia pamięci. A następnie ładuje nowy raport.
Oto przykładowy kod, który mam
Form1:
private ReportDocument rpt;
private void timer2_Tick(object sender, EventArgs e)
{
timer2.Enabled = false;
try
{
panel1.Hide();
if (rpt != null)
{
foreach (Table t in rpd.Database.Tables)
t.Dispose();
rpt.Close();
rpt.Dispose();
rpt = null;
GC.Collect();
}
panel1.Controls.Remove(CRVviewer);
if (CRVviewer != null)
{
CRVviewer.Dispose();
GC.Collect();
}
// The problem starts from here:
var report = navigationbar1.CurrentNode;
rpt = new ReportDocument();
rpt.Load(@report.Path, OpenReportMethod.OpenReportByDefault);
rpt.ReportOptions.EnableSaveDataWithReport = false;
rpt.SetDatabaseLogon(report.UserId, report.Password);
rpt.VerifyDatabase();
// It ends here
CRVviewer = new CrystalReportViewer();
CRVviewer.ReportSource = rpt;
CRVviewer.ShowLastPage();
pagecount = CRVviewer.GetCurrentPageNumber();
CRVviewer.ShowFirstPage();
panel1.Controls.Add(CRVviewer);
this.Update();
}
catch(Exception ex)
{
ProcessErrors(ex);
}
finally
{
timer2.Enabled = true;
}
}
Problem pochodzi z połączenia DB, bo jeśli załadować raportu lokalnego, to działa dobrze. Ale co mam zrobić źle?
Dzięki temu użycie pamięci wydaje się teraz być w porządku, ale uchwyty w menedżerze zadań wciąż rosną. – Apostrofix
EDYCJA: A po kolejnych testach zużycie pamięci wciąż rośnie. – Apostrofix
Możesz chcieć wypróbować profiler pamięci jak [dotMemory] (https://www.jetbrains.com/dotmemory/) Ten jest łatwy w użyciu i ma 5 dni darmowej wersji próbnej. Rozwiązałem problem z pamięcią za pomocą tego narzędzia, gdy miałem podobne problemy z pamięcią w raportach Crystal. Co więcej, Ty też chcesz śledzić wszystkie subskrybowane zdarzenia, które zostały prawidłowo anulowane, szczególnie jeśli masz odniesienie do kryształów w tych wydarzeniach. Spróbuję uruchomić twój kod i sprawdzić, czy mogę znaleźć inny problem? czy to pełny kod? – ANewGuyInTown