อัปเดต (1 ธันวาคม 2009):
ฉันต้องการแก้ไขคำตอบนี้และยอมรับว่าคำตอบเดิมนั้นมีข้อบกพร่อง
การวิเคราะห์เริ่มต้นจะนำไปใช้กับวัตถุที่ต้องการการสรุปและประเด็นที่การปฏิบัติไม่ควรได้รับการยอมรับบนพื้นผิวโดยปราศจากความเข้าใจที่ถูกต้องและลึกซึ้งยังคงมีอยู่
อย่างไรก็ตามปรากฎว่าชุดข้อมูล, DataViews, DataTables ระงับการสรุปในตัวสร้างของพวกเขา - นี่คือเหตุผลที่เรียก Dispose () พวกเขาทำอะไรอย่างชัดเจน
สันนิษฐานว่าเกิดขึ้นเพราะพวกเขาไม่มีทรัพยากรที่ไม่มีการจัดการ ดังนั้นแม้จะมีข้อเท็จจริงที่ว่าMarshalByValueComponentทำเงินสำรองสำหรับทรัพยากรที่ไม่มีการจัดการ แต่การใช้งานเฉพาะเหล่านี้ไม่มีความจำเป็นและสามารถยกเลิกได้
(ผู้เขียน. NET นั้นจะต้องระมัดระวังในการระงับการสรุปในประเภทที่ตามปกติแล้วหน่วยความจำส่วนใหญ่พูดถึงความสำคัญของการปฏิบัตินี้โดยทั่วไปสำหรับประเภทที่สรุปได้)
อย่างไรก็ตามรายละเอียดเหล่านี้ยังไม่ได้รับการจัดทำเอกสารตั้งแต่เริ่มต้นของ. NET Framework (เกือบ 8 ปีที่แล้ว) เป็นเรื่องที่ค่อนข้างน่าแปลกใจ (คุณต้องทิ้งอุปกรณ์ไว้กับตัวเองเพื่อร่อนแม้ว่าวัสดุที่ขัดแย้งกันจะคลุมเครือ บางครั้งก็น่าหงุดหงิด แต่ให้ความเข้าใจที่สมบูรณ์ยิ่งขึ้นเกี่ยวกับกรอบที่เราพึ่งพาทุกวัน)
หลังจากอ่านจำนวนมากนี่คือความเข้าใจของฉัน:
หากวัตถุนั้นต้องการการสรุปมันสามารถครอบครองหน่วยความจำได้นานกว่าที่ต้องการ - นี่คือสาเหตุ: a) ชนิดใด ๆ ที่กำหนด destructor (หรือสืบทอดจากชนิดที่กำหนด destructor) จะถือว่าเป็นวัตถุสุดท้าย b) ในการจัดสรร (ก่อนที่ Constructor จะรัน) ตัวชี้จะถูกวางไว้ในคิว Finalization c) วัตถุที่สามารถทำให้สำเร็จได้โดยปกติจะต้องเรียกคืน2 คอลเลกชัน (แทนที่จะเป็นมาตรฐาน 1) d) การระงับการสรุปไม่ลบวัตถุออกจากคิวการสรุป (ตามที่รายงานโดย! FinalizeQueue ใน SOS) คำสั่งนี้ทำให้เข้าใจผิด; การรู้ว่าวัตถุใดที่อยู่ในคิวการสรุป (ในและของตัวเอง) ไม่มีประโยชน์ การรู้ว่าวัตถุใดที่อยู่ในคิวการสรุปและยังคงต้องการการสรุปจะมีประโยชน์ (มีคำสั่งสำหรับสิ่งนี้หรือไม่)
การระงับการสรุปจะปิดสักเล็กน้อยในส่วนหัวของวัตถุซึ่งระบุถึงรันไทม์ที่ไม่จำเป็นต้องเรียกใช้ Finalizer (ไม่จำเป็นต้องย้ายคิว FReachable) มันยังคงอยู่ในคิวการสรุป (และยังคงถูกรายงานโดย! FinalizeQueue ใน SOS)
คลาส DataTable, DataSet, DataView จะถูกรูททั้งหมดที่ MarshalByValueComponent ซึ่งเป็นออบเจ็กต์สุดท้ายที่สามารถ (อาจ) จัดการกับทรัพยากรที่ไม่มีการจัดการ
- เนื่องจาก DataTable, DataSet, DataView ไม่แนะนำทรัพยากรที่ไม่ได้รับการจัดการจึงหยุดการสรุปในตัวสร้างของพวกเขา
- ขณะนี้เป็นรูปแบบที่ผิดปกติมันช่วยให้ผู้โทรไม่ต้องกังวลเกี่ยวกับการโทรทิ้งหลังจากใช้งาน
- สิ่งนี้และความจริงที่ว่า DataTables สามารถแชร์ข้าม DataSets ต่าง ๆ ได้นั้นเป็นไปได้ว่าทำไม DataSets ไม่สนใจทิ้ง DataTables ย่อย
- นอกจากนี้ยังหมายความว่าวัตถุเหล่านี้จะปรากฏภายใต้! FinalizeQueue ใน SOS
- อย่างไรก็ตามวัตถุเหล่านี้ยังคงสามารถเรียกคืนได้หลังจากการรวบรวมเดี่ยวเช่นคู่ที่ไม่สามารถสรุปได้
4 (การอ้างอิงใหม่):
คำตอบเดิม:
มีคำตอบที่เข้าใจผิดและโดยทั่วไปแย่มาก - ผู้ที่ลงจอดที่นี่ควรเพิกเฉยต่อเสียงรบกวนและอ่านข้อมูลอ้างอิงด้านล่างอย่างระมัดระวัง
ไม่ต้องสงสัยเลยว่า Dispose ควรถูกเรียกใช้บนวัตถุใด ๆ
DataTables มี Finalizable
การโทรทิ้งความเร็วในการเรียกคืนหน่วยความจำอย่างมีนัยสำคัญ
MarshalByValueComponentเรียกGC.SuppressFinalize (นี่)ใน Dispose () - ข้ามวิธีนี้ต้องรอนับสิบถ้าไม่ได้รวบรวมคอลเลกชั่น Gen0 หลายร้อยก่อนที่หน่วยความจำจะถูกเรียกคืน:
ด้วยความเข้าใจพื้นฐานของการสรุปเราสามารถสรุปสิ่งสำคัญบางอย่างได้แล้ว:
ก่อนวัตถุที่ต้องการการสรุปจะมีอายุการใช้งานยาวนานกว่าวัตถุที่ไม่ต้องการ ในความเป็นจริงพวกเขาสามารถมีชีวิตอยู่ได้นานขึ้น ตัวอย่างเช่นสมมติว่าวัตถุที่อยู่ใน gen2 ต้องได้รับการสรุป การสรุปจะกำหนดไว้ แต่วัตถุยังอยู่ใน gen2 ดังนั้นมันจะไม่ถูกรวบรวมใหม่จนกว่าจะมีการรวบรวม gen2 ครั้งต่อไป นั่นอาจเป็นเวลาที่นานมากและในความเป็นจริงถ้าสิ่งต่าง ๆ ดีขึ้นมันจะใช้เวลานานเพราะคอลเลคชั่น gen2 มีราคาแพงและเราต้องการให้พวกเขาเกิดขึ้นไม่บ่อยนัก วัตถุที่เก่ากว่าที่ต้องการการสรุปอาจต้องรอนับสิบ ๆ ครั้งหากไม่ใช่คอลเลกชัน gen0 หลายร้อยรายการก่อนที่จะมีการเรียกคืนพื้นที่ของตน
ประการที่สองวัตถุที่ต้องการการสรุปทำให้เกิดความเสียหายต่อหลักประกัน เนื่องจากพอยน์เตอร์ของวัตถุภายในจะต้องถูกต้องไม่เพียง แต่วัตถุที่ต้องการการสรุปขั้นสุดท้ายในหน่วยความจำเท่านั้น แต่ทุกอย่างที่วัตถุอ้างถึงโดยตรงและโดยอ้อมจะยังคงอยู่ในหน่วยความจำ ถ้าต้นไม้ขนาดใหญ่ของวัตถุถูกยึดโดยวัตถุเดียวที่จำเป็นต้องมีการสรุปแล้วต้นไม้ทั้งหมดจะคงอยู่อาจเป็นเวลานานเมื่อเราเพิ่งพูดคุย ดังนั้นจึงเป็นเรื่องสำคัญที่จะต้องใช้ finalizers อย่างประหยัดและวางลงบนวัตถุที่มีตัวชี้วัตถุภายในน้อยที่สุดเท่าที่จะทำได้ ในตัวอย่างต้นไม้ที่ฉันเพิ่งให้คุณสามารถหลีกเลี่ยงปัญหาได้อย่างง่ายดายโดยการย้ายทรัพยากรที่ต้องการการสรุปไปยังวัตถุแยกต่างหากและทำการอ้างอิงถึงวัตถุนั้นในรากของต้นไม้
ในที่สุดวัตถุที่ต้องการการสรุปจะสร้างงานสำหรับเธรด finalizer หากกระบวนการสรุปของคุณเป็นกระบวนการที่ซับซ้อนเธรด finalizer เพียงรายการเดียวเท่านั้นที่จะใช้เวลาส่วนใหญ่ในการดำเนินการตามขั้นตอนเหล่านี้ซึ่งอาจทำให้งานในมือค้างและทำให้วัตถุอื่น ๆ รอการสรุป ดังนั้นจึงเป็นสิ่งสำคัญอย่างยิ่งที่ผู้เข้ารอบสุดท้ายทำผลงานได้น้อยที่สุด โปรดจำไว้ว่าแม้ว่าตัวชี้วัตถุทั้งหมดยังคงใช้ได้ในระหว่างการสรุปอาจเป็นกรณีที่ตัวชี้เหล่านั้นนำไปสู่วัตถุที่ได้รับการสรุปแล้วและอาจมีประโยชน์น้อยกว่า โดยทั่วไปจะปลอดภัยที่สุดในการหลีกเลี่ยงการติดตามตัวชี้วัตถุในรหัสการสรุปแม้ว่าตัวชี้จะถูกต้อง เส้นทางรหัสสรุปสั้น ๆ ที่ปลอดภัยนั้นดีที่สุด
นำมาจากคนที่เห็น DataTables ที่ไม่ใช่อ้างอิงใน 100s MBs ใน Gen2: นี่เป็นสิ่งที่สำคัญอย่างยิ่งและไม่ได้รับคำตอบจากกระทู้นี้
อ้างอิง:
1 -
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 -
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector ประสิทธิภาพโดยใช้-finalizedispose-pattern.aspx
3 -
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/