Kebocoran memori setelah menutup winform dengan tabel khusus

Saya memiliki dialog C# WinForm yang berisi kontrol tabel khusus dengan baris dan sel yang semuanya juga merupakan kontrol khusus. Setelah menutup (tidak menyembunyikan) dialog ini saya mengalami kebocoran memori (dan ini dikonfirmasi oleh profiler memori .NET).

Dari informasi yang saya dapatkan dari profiler, saya pikir ini berkaitan dengan pembuangan kontrol ini tetapi saya tidak yakin bagaimana cara memperbaikinya.

Dalam kontrol tabel saya memiliki daftar baris:

private readonly List<CustomRow> _rows = new List<CustomRow>(); 

Di setiap baris saya memiliki daftar sel:

List<CustomCell> _cells = new List<CustomCell>();

Saat ini pembuangan kontrol dilakukan dengan kode yang dibuat secara otomatis di designer.cs:

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
         components.Dispose();
    }
    base.Dispose(disposing);
}

Tapi sekarang saya berpikir apakah saya perlu memindahkan kode pembuangan ke file .cs dan menambahkan sesuatu seperti itu, misalnya untuk tabel:

protected override void Dispose(bool disposing)
{
     if (disposing)
     {
          if (components != null)
          {
              components.Dispose();
          }
          // dispose each row here                
     }
     base.Dispose(disposing);
}

Atau ini dilakukan secara otomatis dan alasan kebocoran memori berbeda? (Apa itu?)


person demonplus    schedule 26.12.2015    source sumber
comment
Hanya untuk memastikan, Anda menggunakan Show dan bukan ShowDialog saat menampilkan dialog - hm? Dan metode Dispose dipanggil?   -  person Ivan Stoev    schedule 26.12.2015
comment
@IvanStoev Saya menggunakan Show(), bukan ShowDialog(). Satu hal yang lebih penting adalah bahwa dialog-dialog ini tidak ditampilkan secara langsung tetapi ditambahkan sebagai kontrol ke formulir tab (satu per tab) dan kemudian Show() dipanggil untuk formulir utama   -  person demonplus    schedule 26.12.2015


Jawaban (1)


Pola Dispose berbeda dari yang Anda kira. Dispose tidak mencegah kebocoran memori.

Pola buang digunakan untuk mencegah kebocoran memori yang tidak dikelola menggunakan kode yang tidak dikelola. Artinya, jika Anda menggunakan kode/perpustakaan yang tidak dikelola, Anda harus memanggil deinisialisasi (kode yang tidak dikelola) pada metode Buang.


Masalah yang Anda hadapi adalah Anda memiliki kumpulan data yang umurnya lebih lama dari formulir Anda. Artinya, ketika sebuah kontrol mendaftarkan kejadian pada baris data/tabel (seperti kejadian RowChanged), formulir tetap hidup oleh kontrol data yang direferensikan (karena sebuah eventhandler) oleh kumpulan data. Ingat, event handler adalah referensi yang kuat dan dapat menyebabkan kebocoran memori seperti milik Anda.

Saya tidak tahu komponen apa yang Anda gunakan, tapi Anda mungkin bisa membuat perbaikan mudah untuk ini.

Misal: Saat form sedang close/ditutup, reset saja GridView1.DataSource = Null. Ini akan memaksa komponen untuk membatalkan pendaftaran perubahan/perubahan peristiwa DataTable

jadi cara Anda 'mengikat' data ke komponen, cukup 'melepaskan' dengan cara yang sama dan membuat profil lagi

person Jeroen van Langen    schedule 26.12.2015
comment
Terima kasih, saya rasa Anda mungkin benar. Komponennya ditulis sendiri. Penyatuan data tidak digunakan, untuk menambahkan data hanya menggunakan metode addRow(). Saya dapat menghapus semuanya dengan metode clearAll(). Apakah menurut Anda saya harus mencoba meneleponnya ketika formulir sudah dibuang? - person demonplus; 26.12.2015
comment
Anda harus memeriksa apakah Anda mendaftarkan acara di DataTable/DataSet. Jika ya, batalkan pendaftarannya di Dispose/Closing - person Jeroen van Langen; 26.12.2015