Tất cả những câu hỏi sau:Sử dụng đối tượng Wrapper để đúng dọn dẹp excel interop đối tượng
- Excel 2007 Hangs When Closing via .NET
- How to properly clean up Excel interop objects in C#
- How to properly clean up interop objects in C#
đấu tranh với các vấn đề mà C# không nhả Excel COM đối tượng đúng cách sau khi sử dụng chúng. Có hai hướng chính làm việc xung quanh vấn đề này:
- Giết quy trình Excel khi Excel không còn được sử dụng nữa.
- Cẩn thận chỉ định rõ ràng từng đối tượng COM được sử dụng cho một biến đầu tiên và để đảm bảo rằng cuối cùng, Marshal.ReleaseComObject được thực hiện trên mỗi biến.
Một số đã tuyên bố rằng 2 quá tẻ nhạt và luôn có một số sự không chắc chắn cho dù bạn quên tuân theo quy tắc này tại một số vị trí trong mã. Vẫn còn 1 dường như bẩn và dễ bị lỗi, tôi đoán rằng trong một môi trường bị hạn chế cố gắng để giết một quá trình có thể làm tăng một lỗi bảo mật. Vì vậy, tôi đã suy nghĩ về việc giải quyết 2 bằng cách tạo ra một mô hình đối tượng proxy khác bắt chước mô hình đối tượng Excel (đối với tôi, nó sẽ đủ để thực hiện các đối tượng mà tôi thực sự cần). Nguyên tắc sẽ trông như sau:
- Mỗi lớp Interop của Excel có proxy bao bọc đối tượng của lớp đó.
- Proxy giải phóng đối tượng COM trong trình hoàn thiện của nó.
- Proxy bắt chước giao diện của lớp Interop.
- Bất kỳ phương thức nào ban đầu trả lại đối tượng COM được thay đổi để trả lại proxy thay thế. Các phương thức khác chỉ đơn giản là ủy nhiệm việc triển khai thực hiện đối tượng COM bên trong.
Ví dụ:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
Câu hỏi của tôi cho bạn là đặc biệt:
- Ai này tìm thấy một ý tưởng tồi và tại sao?
- Ai tìm thấy ý tưởng này? Nếu vậy, tại sao không ai thực hiện/xuất bản một mô hình như vậy chưa? Có phải chỉ vì nỗ lực đó, hay tôi đang thiếu một vấn đề giết người với ý tưởng đó?
- Có thể không/xấu/dễ xảy ra lỗi khi ReleaseCOMObject trong trình hoàn tất không? (Tôi đã chỉ thấy các đề xuất để đưa nó vào một Dispose() thay vì trong một finalizer - tại sao?)
- Nếu cách tiếp cận có ý nghĩa, bất kỳ đề xuất để cải thiện nó?
Bạn đang đúng với finalizer ở gốc, nhưng trong tình huống đặc biệt này, tôi có thể nói: Chúng ta hãy ủy thác trách nhiệm thu gom rác, vì do finalizer tôi có thể dựa vào GC cũng phát hành đối tượng COM ngay khi đối tượng bên trong bị phá hủy. Nếu tôi muốn phát hành rõ ràng tất cả các tài nguyên ở một số nơi trên mã, tôi có thể sử dụng GC.Collect(). – chiccodoro
@chiccodoro: Vấn đề với phương pháp này là nó dựa vào chi tiết triển khai của GC. Nếu GC thay đổi một chút, nó có thể không hoạt động nữa. Nhưng tôi hiểu sự khó khăn của việc thực hiện nó một cách đúng đắn trong tình huống này, và rằng hack có thể là giải pháp tiết kiệm chi phí nhất trong một số tình huống. –
Hmm. Tôi thấy điểm của bạn. Nhưng việc sử dụng() cho mỗi dấu chấm đơn giản là tẻ nhạt. Có lẽ chỉ định nghĩa một phương thức Dispose() trên Excel.Application chạy GC.Collect() để tất cả các đối tượng Excel khác cũng được giải phóng vào thời điểm này? Cho đến khi Excel.Application lá phạm vi "sử dụng", tôi không yêu cầu chương trình của tôi để phát hành tài nguyên COM xuất phát từ ứng dụng. – chiccodoro