หน่วยความจำรั่วหลังจากปิด winform ด้วยตารางที่กำหนดเอง

ฉันมีกล่องโต้ตอบ C# WinForm ซึ่งมีการควบคุมตารางแบบกำหนดเองพร้อมแถวและเซลล์ซึ่งเป็นการควบคุมแบบกำหนดเองทั้งหมดเช่นกัน หลังจากปิด (ไม่ซ่อน) กล่องโต้ตอบนี้ฉันมีหน่วยความจำรั่ว (และได้รับการยืนยันโดยผู้สร้างโปรไฟล์หน่วยความจำ .NET)

จากข้อมูลที่ฉันได้รับจากผู้สร้างโปรไฟล์ ฉันคิดว่ามันเกี่ยวข้องกับการกำจัดการควบคุมเหล่านี้ แต่ฉันไม่แน่ใจว่าจะแก้ไขได้อย่างไร

ในการควบคุมตารางฉันมีรายการแถว:

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

ในแต่ละแถวฉันมีรายการเซลล์:

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

ตอนนี้การกำจัดในการควบคุมเสร็จสิ้นโดยโค้ดที่สร้างขึ้นอัตโนมัติใน designer.cs:

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

แต่ตอนนี้ ฉันคิดว่าฉันต้องย้ายโค้ดการกำจัดไปยังไฟล์ .cs และเพิ่มอะไรทำนองนั้นหรือไม่ เช่น สำหรับตาราง:

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

หรือดำเนินการโดยอัตโนมัติและเหตุผลของหน่วยความจำรั่วแตกต่างออกไป (มันจะเป็นอะไรได้?)


person demonplus    schedule 26.12.2015    source แหล่งที่มา
comment
เพียงเพื่อให้แน่ใจว่าคุณใช้ Show และไม่ใช่ ShowDialog เมื่อแสดง - หืม กล่องโต้ตอบเหรอ? และวิธีการ Dispose เรียกว่า?   -  person Ivan Stoev    schedule 26.12.2015
comment
@IvanStoev ฉันใช้ Show() ไม่ใช่ ShowDialog() สิ่งสำคัญอีกประการหนึ่งคือกล่องโต้ตอบเหล่านี้จะไม่แสดงโดยตรง แต่ถูกเพิ่มเป็นตัวควบคุมให้กับฟอร์มแบบแท็บ (หนึ่งรายการต่อแท็บ) จากนั้น Show() จะถูกเรียกสำหรับฟอร์มหลัก   -  person demonplus    schedule 26.12.2015


คำตอบ (1)


รูปแบบของ Dispose แตกต่างจากที่คุณคิด Dispose ไม่ได้ป้องกันการรั่วไหลของหน่วยความจำ

รูปแบบการกำจัดใช้เพื่อป้องกันการรั่วไหลของหน่วยความจำที่ไม่มีการจัดการโดยใช้โค้ดที่ไม่มีการจัดการ ความหมาย หากคุณใช้โค้ด/ไลบรารีที่ไม่มีการจัดการ คุณควรเรียกใช้ deinitialize (ของโค้ดที่ไม่มีการจัดการ) ในเมธอด Dispose


ปัญหาที่คุณกำลังเผชิญคือคุณมีชุดข้อมูลที่มีอายุนานกว่าแบบฟอร์มของคุณ ความหมาย เมื่อตัวควบคุมลงทะเบียนเหตุการณ์บน datarow/ตาราง (เช่น RowChanged events) แบบฟอร์มจะ คงอยู่ โดยตัวควบคุมข้อมูลที่อ้างอิง (เนื่องจาก ตัวจัดการเหตุการณ์) โดยชุดข้อมูล โปรดจำไว้ว่า ตัวจัดการเหตุการณ์เป็นข้อมูลอ้างอิงที่ชัดเจน และอาจทำให้ความทรงจำรั่วไหลได้เช่นเดียวกับคุณ

ฉันไม่รู้ว่าคุณใช้ส่วนประกอบใด แต่คุณอาจสร้างวิธีแก้ไขง่ายๆ สำหรับสิ่งนี้ได้

ตัวอย่างเช่น: เมื่อแบบฟอร์มกำลังปิด/ปิด ให้รีเซ็ต GridView1.DataSource = Null สิ่งนี้จะบังคับให้คอมโพเนนต์ยกเลิกการลงทะเบียนเหตุการณ์การเปลี่ยนแปลง/การเปลี่ยนแปลงของ DataTable

ดังนั้น วิธีที่คุณ 'ผูก' ข้อมูลกับส่วนประกอบ เพียงแค่ 'แยก' มันด้วยวิธีเดียวกันและทำโปรไฟล์อีกครั้ง

person Jeroen van Langen    schedule 26.12.2015
comment
ขอบคุณ ฉันคิดว่าคุณอาจจะถูกต้อง ส่วนประกอบเขียนด้วยตัวเราเอง ไม่ได้ใช้ Databinding ในการเพิ่มข้อมูล จะใช้เพียงวิธี addRow() เท่านั้น ฉันสามารถล้างทุกอย่างได้โดยวิธี clearAll() คุณคิดว่าฉันควรพยายามเรียกมันเมื่อรูปแบบถูกกำจัดหรือไม่? - person demonplus; 26.12.2015
comment
คุณควรตรวจสอบว่าคุณกำลังลงทะเบียนกิจกรรมใน DataTable/DataSet หรือไม่ หากเป็นเช่นนั้น ให้ยกเลิกการลงทะเบียนในการกำจัด/การปิด - person Jeroen van Langen; 26.12.2015