2010-08-11 21 views
16

Trình hoàn tất có được bảo đảm thực hiện tại .NET tại một số điểm (mất điện dự phòng và các loại tương tự) không? Tôi biết GC hoạt động như thế nào và điều đó là không xác định khi chính xác họ sẽ chạy.Các trình kết thúc .net luôn được thực hiện?

(Tìm kiếm không hiển thị câu trả lời hay, vì vậy tôi thêm câu hỏi này với kỳ vọng cao về việc hợp nhất với các câu trả lời không thực sự dễ khám phá. Ngoài ra, tôi đã biết câu trả lời và sẽ thêm nó sau một vài ngày trong trường hợp không ai đề cập đến nó.)

Trả lời

24

bộ hoàn thiện thực sự có thể không bao giờ thực hiện, như Raymond Chen explains. Loại hài hước rằng câu hỏi này được hỏi trong tuần CLR hàng năm của mình, chỉ hai ngày sau khi ông giải thích nó :)

Đối với những người lười biếng, các (hay đúng hơn, một) kết luận là:

Một cách chính xác chương trình viết không thể giả định rằng finalizers sẽ bao giờ chạy.

Nếu bạn đang tự hỏi liệu bạn có thể dựa vào finalizers hay không, đây là tất cả mọi thứ bạn cần biết: Đừng dựa vào finalizers.

Như Raymond Chen cũng nói trong bài viết liên quan:

bộ hoàn thiện là một mạng lưới an toàn, không phải là một phương tiện chủ yếu cho cải tạo tài nguyên.

Nếu bạn đang tìm cách giải phóng tài nguyên, hãy xem mẫu Dùng một lần.


Một finalizer có thể không chạy, ví dụ, nếu:

  • finalizer Một ném một ngoại lệ.
  • Trình hoàn thành khác mất hơn 2 giây.
  • Tất cả các finalizers cùng nhau mất hơn 40 giây.
  • Một AppDomain bị treo hoặc được bốc dỡ (mặc dù bạn có thể phá vỡ này với một finalizer quan trọng (CriticalFinalizerObject, SafeHandle hoặc một cái gì đó như thế)
  • Không thu gom rác thải xảy ra
  • Quá trình này bị treo

(Lưu ý: Các giá trị thời gian có thể đã thay đổi theo thời gian, but were certainly true some time ago.)

Tôi đoán có rất nhiều thứ có thể khiến các finalizers không bao giờ chạy. an toàn net th tại giảm tác động của lỗi, vì tài nguyên ví dụ được phát hành đôi khi, tốt hơn không bao giờ, nếu bạn quên làm điều đó một cách dễ hiểu.

+0

Bạn có thể trích dẫn thêm của các bộ phận quan trọng? Và vâng, có lẽ người hỏi đang mong chờ chính xác liên kết đó. ;) – mafu

+0

Trên thực tế, vì nhiều người hỏi làm thế nào họ có thể dựa vào hành vi finalizer, tôi nghĩ rằng tôi * đã * trích dẫn một phần quan trọng nhất;) Mặt khác, các hộp khác trong bài viết có thể là thú vị là tốt. – OregonGhost

+0

@OregonGhost: Tôi có hiểu được quyền này không: nếu 20 người kết thúc mỗi người mất 1.95 giây, đó là lý do hunky và tất cả sẽ thi hành - mất 39 giây. Nếu một mất 2.05 giây, thực hiện tất cả những người khác bị bỏ qua. Điều đó có vẻ khá hỏng. Thay vì làm gián đoạn một finalizer mất hơn 2 giây, với mục đích cho phép những người khác chạy trong phần còn lại của thời gian chờ 40 giây, sẽ là một tính năng tốt. Nhưng những thứ sau khi ăn cắp sau hai giây có vẻ như là một sự không hài lòng. – supercat

6

Nếu trình kết thúc ném một ngoại lệ, các finalizers khác sẽ không thực thi.

Bạn cũng có thể chặn các finalizers nếu bạn gọi SuppressFinalizer trên đối tượng.

Từ MSDN (Object.Finalize):

Phương pháp Finalize có thể không chạy đến khi kết thúc hoặc có thể không chạy ở tất cả trong các trường hợp đặc biệt sau đây:

  • Một khối finalizer vô thời hạn (đi vào một vòng lặp vô hạn, cố gắng để có được một khóa nó không bao giờ có thể có được và như vậy). Bởi vì thời gian chạy cố gắng để chạy finalizers để hoàn thành, finalizers khác có thể không được gọi nếu một finalizer khối vô thời hạn.
  • Quá trình chấm dứt mà không cho thời gian chạy có cơ hội để làm sạch. Trong trường hợp này, thông báo đầu tiên của quá trình chấm dứt quá trình là một thông báo DLL_PROCESS_DETACH.
+0

Bạn có thể thêm nguồn cho phần "ngoại lệ" không? – mafu

+0

Lưu ý rằng "đi vào một vòng lặp vô hạn", trong thực hiện CLR, có nghĩa là "mất hơn hai giây", như được giải thích ở đây: http://nitoprograms.blogspot.com/2009/08/finalizers-at-process- exit.html – OregonGhost

+0

@mafutrct - Xem tại đây: http://stackoverflow.com/questions/1538630/exceptions-during-finalize-what-methodology-are-you-using-to-detect-garbage-co – Oded

Các vấn đề liên quan