2011-07-18 30 views
9

Trình hoàn thành luôn được gọi bởi khung .net, do đó chuỗi có thể nằm ngoài tầm kiểm soát; và thậm chí nếu constructor thất bại, destructor vẫn có thể được kích hoạt.C#: Làm thế nào để xử lý các ngoại lệ finalizer từ thư viện của bên thứ 3?

Điều này có thể mang lại những rắc rối, khi ngoại lệ của trình hoàn tất đó đến từ thư viện của bên thứ ba: Tôi không thể tìm cách xử lý chúng! Ví dụ, trong đoạn code dưới đây, mặc dù constructor lớp A luôn ném một ngoại lệ và thất bại, finalizer của A sẽ được kích hoạt bởi khung .net, cũng ~ B() được gọi là A có thuộc tính kiểu B .

class Program // my code 
{ 
    static void Main(string[] args) 
    { 
     A objA; 
     try 
     { 
      objA = new A(); 
     } 
     catch (Exception) 
     { 
     } 

     ; // when A() throws an exception, objA is null 

     GC.Collect(); // however, this can force ~A() and ~B() to be called. 

     Console.ReadLine(); 
    } 
} 

public class A // 3rd-party code 
{ 
    public B objB; 

    public A() 
    { 
     objB = new B(); // this will lead ~B() to be called. 
     throw new Exception("Exception in A()"); 
    } 

    ~A() // called by .net framework 
    { 
     throw new Exception("Exception in ~A()"); // bad coding but I can't modify 
    } 
} 

public class B // 3rd-party code 
{ 
    public B() { } 

    ~B() // called by .net framework 
    { 
     throw new Exception("Exception in ~B()"); // bad coding but I can't modify 
    } 
} 

Nếu đây là mã của tôi, nó là một chút dễ dàng hơn - Tôi có thể sử dụng try-catch trong finalizers, ít nhất tôi có thể làm một số khai thác gỗ - Tôi có thể cho phép các ngoại lệ sụp đổ chương trình, để khám phá các lỗi asap - hoặc nếu tôi muốn "chịu đựng" ngoại lệ, tôi có thể có một thử-catch để ngăn chặn các ngoại lệ, và có một lối ra duyên dáng.

Nhưng nếu A và B là các lớp học từ thư viện của bên thứ ba, tôi không thể làm gì cả! Tôi không thể kiểm soát ngoại lệ xảy ra, tôi không thể bắt chúng, vì vậy tôi không thể đăng nhập hoặc ngăn chặn nó!

Tôi có thể làm gì?

+1

+1 Sự cố thú vị (và trong khi chờ đợi, hãy báo cáo lỗi khẩn cấp với các nhà cung cấp thư viện cung cấp 'A' và' B'). – Ergwun

+0

^^ - Điểm tuyệt vời. Cần phải là một câu trả lời thực tế. –

Trả lời

2

Âm thanh như tiện ích của bên thứ ba được viết kém. :)

Bạn đã thử bắt nó bằng cách sử dụng AppDomain.UnhandledException?

+0

vâng, tôi đang làm điều này ngay bây giờ. nó có thể đăng nhập, nhưng ... không thể thoát ra một cách duyên dáng ... – athos

0

Bạn có thể muốn xem xét một trình xử lý ngoại lệ toàn cục cho ứng dụng của mình. Bạn không cho biết nếu bạn làm ASP.NET, WinForm, MVC, vv, nhưng đây là một ứng dụng cho một giao diện điều khiển:

.NET Global exception handler in console application

Trong ASP.NET, bạn có thể sử dụng các tập tin Global.asax để bắt các ngoại lệ chưa được giải quyết.

Nếu bạn luôn gọi GC.Collect() trong ứng dụng của mình, bạn có thể thử gói trong khối try-catch.

Chỉ cần một số ý tưởng để xem xét.

0

Bạn có thể sử dụng GC.SuppressFinalizer(objA)GC.KeepAlive(objA) mà sẽ ngăn chặn việc thu gom rác từ gọi Finalize trên đối tượng đó, và vì vậy khi sử dụng KeepAlive các objB sẽ không hoàn thiện vì objA "đó là còn sống" vẫn còn có tài liệu tham khảo của nó. tuy nhiên, bạn nên nhận biết từ rò rỉ bộ nhớ nếu bạn quên hoàn thành hoặc hủy bỏ objA một cách thích hợp.

Nhưng giả sử rằng objA tại một số điểm trong phương pháp chẳng hạn đã khởi tạo objectB khác và không loại bỏ đúng cách, Rất tiếc, tôi không thể làm gì được.

Một điều bạn có thể thử là kiểm tra xem thư viện đó có hoạt động khác khi bạn ở chế độ Release thay vì chế độ Debug hay không; ví dụ, họ có thể chỉ ném ngoại lệ vào finalizer nếu nó được gọi trong chế độ gỡ lỗi "nó là loại trợ giúp cho các nhà phát triển vì vậy nếu họ không gọi vứt bỏ hoặc hoàn thành đối tượng theo cách đúng, ngoại lệ sẽ ném trong khi gỡ lỗi":

~A() 
{ 
#if DEBUG 
    throw new Exception("Exception in ~A()"); 
#endif//DEBUG 
} 

Nếu đó không phải là trường hợp, sau đó tôi nghĩ rằng bạn sẽ có một ngày tồi tệ đối phó với thư viện đó.

+0

xin lỗi Jordan, tôi nghĩ rằng tôi đã không đặt câu hỏi của tôi rõ ràng, để bạn có thể có một sự hiểu lầm về nó. – athos

+0

@athos: Xin lỗi, tôi đã đọc lại câu hỏi của bạn và đã tìm ra rằng tôi đã bỏ lỡ thực tế là 'objA' là null! –

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