2012-03-14 28 views
7

Giả sử tôi có đối tượng COM (không được quản lý) và .NET Client.Khả năng tương thích .NET và COM: phát hành COM từ máy khách .NET

Có cần phải gọi từ phương thức .NET client Marshal.FinalReleaseComObject để giải phóng đối tượng COM không?

+3

http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx –

+0

Cảm ơn - bài viết rất hữu ích –

Trả lời

2

Không. Không cần phải giải phóng rõ ràng đối tượng COM từ ứng dụng khách Net. Đối tượng COM sẽ được thu thập giống như bất kỳ đối tượng .Net khác và sẽ giải phóng xử lý gốc cơ bản của nó khi tất cả các tham chiếu đến nó được loại bỏ.

Sử dụng rõ ràng FinalReleaseComObject thực sự có thể dẫn đến lỗi lập trình. Nếu một thành phần khác trong mã của bạn vẫn đang tham chiếu đến đối tượng COM, bạn sẽ yanking ra đối tượng gốc từ bên dưới nó. Điều đó có thể dẫn đến thất bại thời gian chạy xuống đường.

+0

Trong khi "trong lý thuyết" có thể không có cần, "trong thực tế", có * chắc chắn là *. Ngoài ra, không sử dụng FinalReleaseComObject, nhưng thay vì ReleaseComObject cho * mỗi lần bất kỳ đối tượng * COM nào đã được đưa qua ranh giới COM-.NET. Tôi làm Outlook Addin lập trình: và tôi có thể nói, cho các đối tượng * đời sống rõ ràng là cách duy nhất để tạo một bổ trợ làm việc *. Giai đoạn. (Tôi sử dụng một lớp helper/wrapper hỗ trợ Dispose I sử dụng với 'using'.) –

+3

Thực hành sai. Bạn GC.Collect() + GC.WaitForPendingFinalizers() nếu bạn phải, không bao giờ sai. –

+1

@HansPassant Điều đó không hoạt động với Mô hình đối tượng Outlook. "Các giải pháp" liên quan khác nhau liên quan đến việc cố gắng gọi trình tự đó * hai lần * liên tiếp. Nó chỉ không hoạt động "trong thực tế" (trong trường hợp tôi đối phó với). –

2

A sửa đổi "Có" và "Không".

Trước hết, hãy nhớ rằng ReleaseComObjectkhông sẽ tự động giảm số lần đối tượng COM thực. Thay vào đó nó làm giảm bộ đếm RCW bên trong. (Mỗi khi cùng một đối tượng COM COM được di chuyển từ COM-> NET, nó sẽ sử dụng cùng một RCW và tăng bộ đếm RCW.) Tương tự, FinalRelaseComObject cũng ảnh hưởng đến bộ đếm RCW "đặt thành 0". Đó là khi bộ đếm RCW bằng không, .NET sẽ giảm số lượng thực tế COM.

Vì vậy, "yes", nhưng sửa đổi cho những quy tắc:

  1. Mỗi lần một đối tượng đường chuyền từ com-> NET nó nênReleaseComObject, nhưng khôngFinalReleaseComObject , được viện dẫn. Tức là, nó phải được gọi một lần cho mỗi lần đối tượng đi qua, ngay cả khi nó dẫn đến tham chiếu bằng RCW.
  2. Số lượng tham chiếu đến RCW (chỉ là trình bao bọc proxy) không quan trọng; chỉ những lần đối tượng đã vượt qua ranh giới. Xem quy tắc số 1. (Điều quan trọng là để kiểm soát tài liệu tham khảo và những người giữ chúng, nhưng "tồi tệ nhất" điều đó xảy ra trong trường hợp này là một ngoại lệ từ việc sử dụng một "RCW tách ra", đó là không khác vì sử dụng một dòng xử lý.)

tôi nói các quy tắc trên và khôngFinalReleaseComObject vì các đối tượng RCW được lưu trữ trong một proxy sắc, vì vậy sử dụng FinalReleaseComObjectsẽ ảnh hưởng đến com-> cửa ranh giới NET bạn thậm chí không biết về! (Đây là xấu và, vào thời điểm này, tôi hoàn toàn đồng ý với JaredPars câu trả lời.)

"không" trong đó, khi một RCW được khai hoang (finalizer được gọi là), nó sẽ tự động "phát hành" tài liệu tham khảo COM (tự động gọi số FinalReleaseComObject). Hãy nhớ rằng vì chỉ có một đối tượng RCW điều này có nghĩa là nó sẽ không bao giờ được khai hoang miễn là có một tham chiếu đến nó trong .NET.Nếu RCW được khai hoang có không có vấn đề vì, từ trên, không có tham chiếu nào cho RCW nói trên và do đó .NET biết nó có thể giảm số đếm COM bằng một (có thể khiến đối tượng COM bị hủy) .

Tuy nhiên, vì .NET GC là khó và không xác định, dựa vào hành vi này có nghĩa là thời gian tồn tại đối tượng không được kiểm soát. Điều này có thể gây ra nhiều các vấn đề tinh tế khi làm việc với Mô hình Đối tượng Outlook, chẳng hạn. (Nó có thể ít bị các vấn đề với các máy chủ COM khác, nhưng OOM làm hài lòng "bộ nhớ đệm" của các đối tượng trong nội bộ. Thật dễ dàng để có được một "Mục đã được sửa đổi" ngoại lệ khi không kiểm soát vòng đời một cách rõ ràng.)

Trong mã của tôi, tôi có một lớp ComWrapper hỗ trợ IDisposable. Điều này cho phép tôi vượt qua các đối tượng RCW thu được từ COM-> NET với quyền sở hữu rõ ràng suốt đời. Tôi đã có rất ít vấn đề (hầu như không, thực sự) trong quá trình phát triển Outlook-Addin của tôi sau khi chuyển sang phương pháp này và nhiều sự cố trước khi thực hiện. "Nhược điểm" là ranh giới COM-> NET cần phải được xác định, nhưng một khi đó là, sau đó nội bộ tất cả các đời được xử lý một cách chính xác.

Mã hóa vui vẻ.