2011-07-19 28 views
8

Tôi đang cố gắng tìm một cách an toàn/xác định để phát hành một giao diện được đóng gói trong một OleVariant.Cách chính xác để giải phóng một giao diện đằng sau một OleVariant là gì?

AFAICS Delphi phát hành tham chiếu giao diện ở phần cuối của quy trình, nhưng trong trường hợp của tôi, tôi phải thực hiện trước đó, vì tôi phải tắt COM.

Tôi mặc dù đưa OleVariant vào thể hiện lớp phụ mà tôi có thể miễn phí trước khi gọi CoUninitialize.

procedure Test; 
var 
    Container: TLibraryContainer; // Holds the OleVariant 
begin 
    CoInitialize(nil); 
    try 
    Container := TLibraryContainer.Create; 
    try 
     {...} 
    finally 
     Container.Free; 
    end; 
    finally 
    CoUninitialize; 
    end; 
end; 

Giải pháp này an toàn hoặc có giải pháp tốt hơn mà tôi đã bỏ qua?

Trả lời

9

Trình biên dịch rõ ràng đang sử dụng biến giao diện cục bộ ẩn cho giá trị trả về từ CreateOleObject. Điều này sau đó được phát hành vào cuối thói quen, quá muộn cho bạn.

Có một số cách để đánh bại điều này. Trước hết, bạn có thể rõ ràng về tham chiếu giao diện IDispatch được trả về bởi CreateOleObject. Điều này cho phép bạn kiểm soát tuổi thọ của nó.

procedure Test; 
var 
    intf: IDispatch; 
    LLibrary: OleVariant; 
begin 
    CoInitialize(nil); 
    try 
    intf := CreateOleObject(LibraryName); 
    try 
     LLibrary := intf; 
    finally 
     VarClear(LLibrary); 
     intf := nil; 
    end; 
    finally 
    CoUninitialize; 
    end; 
end; 

Cách khác là di chuyển mã gọi là CreateOleObject thành một quy trình riêng biệt với phạm vi riêng.

procedure DoWork; 
var 
    LLibrary: OleVariant; 
begin 
    LLibrary := CreateOleObject(LibraryName); 
    //do stuff with LLibrary 
end; 

procedure Test; 
begin 
    CoInitialize(nil); 
    try 
    DoWork; 
    finally 
    CoUninitialize; 
    end; 
end; 

Kể từ khi tham khảo địa phương tiềm ẩn nằm trong phạm vi của DoWork nó được phát hành vào cuối DoWork và do đó trước khi bạn chạy CoUninitialize.

Đề xuất của tôi là sử dụng tùy chọn thứ hai sạch hơn và buộc trình biên dịch thực hiện công việc thay cho bạn.

+2

Tùy chọn thực sự duy nhất là sử dụng thường trình phụ, trừ khi bạn tận hưởng các cuộc gọi hàm đếm và kiểm tra mã trình tạo được tạo để đảm bảo không có biến cục bộ ẩn. 1 để gọi quy trình 'DoWork' của bạn ...' DoWork', xem câu trả lời đã xóa của tôi để biết chi tiết. –

+0

@Cosmin Tôi đồng ý rằng tùy chọn thứ hai tốt hơn. –

+0

Trên thực tế mã thực sự của tôi phức tạp hơn một chút và tôi nghĩ rằng tôi sẽ phải sử dụng biến thể đầu tiên của bạn, nhưng tôi sẽ cố gắng cấu trúc lại mã để tôi có thể sử dụng mã thứ hai. :) –

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