2011-08-22 34 views
15

Tôi có một ứng dụng chạy quá trình xử lý hàng loạt trong đó nhiều trường hợp ngoại lệ có thể bị ném. Nếu một ngoại lệ không quan trọng được ném trong một mục trong lô, tôi chỉ muốn đăng nhập và tiếp tục, vì vậy chúng tôi có thể khắc phục vấn đề sau trong khi cho phép các mục hàng loạt khác tiếp tục.Tôi nên bắt những ngoại lệ nào?

Một số ngoại lệ, chẳng hạn như OutOfMemoryException, đang tàn phá toàn bộ ứng dụng và những điều này tôi muốn quay lại để chúng bong bóng đến trình xử lý ngoại lệ toàn cục, sẽ ghi nhật ký và dừng ứng dụng. Vì vậy, câu hỏi của tôi là, có một danh sách ngắn các trường hợp ngoại lệ quan trọng mà tôi có thể trả lại trong trình xử lý ngoại lệ của mình trong khi triệt tiêu (sau khi đăng nhập) mọi thứ khác không? Không.

Cảm ơn!

Edit: Để xây dựng một chút, đây là cấu trúc cơ bản của chương trình của tôi

foreach(var item in longItemList) 
{ 
    try 
    { 
     bigDynamicDispatchMethod(item); 
    } 
    catch(Exception ex) 
    { 
     logException(ex); 
    } 
}

Có khả năng một số lượng lớn các trường hợp ngoại lệ có thể được ném bởi vì vòng này là khá nhiều ở cấp cao nhất ứng dụng của tôi. 99% mã trong dự án của tôi nằm phía sau phương thức công văn. Tôi xử lý ngoại lệ hợp lý ở các mức thấp hơn, nhưng các lỗi vẫn hoạt động theo cách của họ và tôi không muốn dừng các quy trình không liên quan khác trong lô sau khi một ngoại lệ được ném ra.

Cố gắng tìm những ngoại lệ nào có thể được ném ở mọi nơi khác trong ứng dụng của tôi có vẻ như một nhiệm vụ khó khăn, và dường như sẽ đơn giản hơn nếu có danh sách đen các trường hợp ngoại lệ quan trọng.

Có cách nào tốt hơn để cấu trúc ứng dụng của tôi để giải quyết vấn đề này không? Tôi đang mở để gợi ý.

+0

thể trùng lặp của [những loại ngoại lệ không bắt?] (http://stackoverflow.com/questions/5507836/which-types- của ngoại lệ-không-để-bắt) –

Trả lời

24

Bạn không cần danh sách ngoại lệ 'xấu', bạn nên xử lý mọi thứ là xấu theo mặc định. Chỉ bắt những gì bạn có thể xử lý và phục hồi. CLR cannotify bạn về các ngoại lệ chưa được xử lý để bạn có thể ghi lại chúng một cách thích hợp. Nuốt tất cả mọi thứ trừ một ngoại lệ được liệt kê đen không phải là cách thích hợp để sửa lỗi của bạn. Điều đó sẽ chỉ che giấu chúng. Đọc thisthis.

Đừng loại trừ bất kỳ trường hợp ngoại lệ đặc biệt khi đánh bắt với mục đích chuyển ngoại lệ.

Thay vì tạo danh sách ngoại lệ đặc biệt trong điều khoản bắt của bạn, bạn chỉ nên bắt những ngoại lệ đó mà bạn có thể hợp pháp xử lý. Các ngoại lệ mà bạn không thể xử lý không được coi là trường hợp đặc biệt trong các trường hợp đặc biệt không xử lý ngoại lệ của . Ví dụ mã sau minh họa việc kiểm tra không chính xác cho các trường hợp ngoại lệ đặc biệt cho mục đích vứt lại chúng.

public class BadExceptionHandlingExample2 { 
    public void DoWork() { 
     // Do some work that might throw exceptions. 
    } 
    public void MethodWithBadHandler() { 
     try { 
      DoWork(); 
     } catch (Exception e) { 
      if (e is StackOverflowException || 
       e is OutOfMemoryException) 
       throw; 
      // Handle the exception and 
      // continue executing. 
     } 
    } 
} 

vài quy tắc khác: xử lý

Tránh lỗi bằng cách bắt ngoại lệ không rõ ràng, chẳng hạn như System.Exception, System.SystemException, và như vậy, trong ứng dụng mã. Có những trường hợp khi xử lý lỗi trong các ứng dụng là có thể chấp nhận được, nhưng những trường hợp như vậy rất hiếm.

Một ứng dụng không được xử lý các ngoại lệ có thể dẫn đến trạng thái không mong muốn hoặc có thể khai thác được . Nếu bạn không thể dự đoán tất cả các nguyên nhân có thể của ngoại lệ và đảm bảo rằng mã độc không thể khai thác trạng thái ứng dụng kết quả, bạn nên cho phép ứng dụng chấm dứt thay vì xử lý ngoại lệ.

Cân nhắc việc bắt ngoại lệ cụ thể khi bạn hiểu tại sao nó sẽ được ném trong một ngữ cảnh nhất định.

Bạn chỉ nên bắt những ngoại lệ mà bạn có thể khôi phục. Đối với ví dụ , một FileNotFoundException do nỗ lực mở một tệp không tồn tại có thể được ứng dụng xử lý vì nó có thể truyền đạt sự cố cho người dùng và cho phép người dùng chỉ định tên tệp khác nhau hoặc tạo tệp . Yêu cầu mở tệp không được xử lý ExecutionEngineException vì nguyên nhân cơ bản của ngoại lệ không được biết với bất kỳ mức độ nào là và ứng dụng không thể đảm bảo an toàn để tiếp tục thực thi.

Eric Lippert phân loại tất cả ngoại lệ thành 4 nhóm: Gây tử vong, 'Boneheaded', Vexing, Exogenous. Sau đây là giải thích của tôi về lời khuyên của Eric:

Exc. type | What to do       | Example 
------------|-------------------------------------|------------------- 
Fatal  | nothing, let CLR handle it   | OutOfMemoryException 
------------|-------------------------------------|------------------- 
Boneheaded | fix the bug that caused exception | ArgumentNullException 
------------|-------------------------------------|------------------- 
Vexing  | fix the bug that caused exception | FormatException from 
      | (by catching exception because  | Guid constructor 
      | the framework provides no other way | (fixed in .NET 4.0 
      | way of handling). Open MS Connect | by Guid.TryParse) 
      | issue.        | 
------------|-------------------------------------|------------------- 
Exogenous | handle exception programmatically | FileNotFoundException 

Đây là tương đương với Microsoft's loại: Trang sử dụng, lỗi chương trình và thất bại hệ thống. Bạn cũng có thể sử dụng các công cụ phân tích tĩnh như FxCop để thực thi some các quy tắc này.

+3

Bạn cũng có thể xử lý các ngoại lệ vexing. Họ rất phật ý vì bạn * phải * xử lý chúng trong hầu hết các tình huống. –

+0

@Eric: Tôi đã cập nhật câu trả lời với giải thích của tôi về bài viết của bạn, hy vọng tôi đã làm đúng. – Dmitry

+2

Có vẻ tuyệt vời! ___ –

11

Không bắt bất kỳ ngoại lệ nào mà bạn không biết cách xử lý an toàn.

Bắt Exception là một thực tế đặc biệt không tốt, chỉ có một điều tồi tệ nhất là catch không chỉ định bất kỳ loại ngoại lệ được quản lý nào (vì nó cũng sẽ thu hút ngoại lệ không được quản lý).

+0

.NET 2.0 sẽ tự động bọc ngoại lệ không tuân thủ CLS (nghĩa là, bất kỳ ngoại lệ nào mà lớp không thừa kế từ Ngoại lệ) s RuntimeWrappedException khi trình bày chúng để bắt các khối trong mã tuân thủ CLS; vì vậy không có lý do gì để sử dụng các khối catchless ở tất cả. –

+0

Tôi làm theo lời khuyên này trong hầu hết các trường hợp, nhưng đây là một phần của một trường hợp đặc biệt. Xem chỉnh sửa. –

1

Thiết kế phù hợp hơn sẽ được hỗ trợ bởi câu hỏi: Which exceptionsnên Tôi bắt?

Nếu bạn thực sự cần nắm bắt bất kỳ và tất cả ngoại lệ và vẫn tiếp tục, thì bạn nên sử dụng cả hai quy trình AppDomain và các quy trình công nhân riêng biệt. Hoặc thay đổi máy chủ của bạn thành ASP.NET hoặc công cụ lập lịch tác vụ, đã thực hiện tất cả công việc khó khăn xung quanh quá trình cô lập và thử lại.

+0

Cảm ơn vì điều này, đây là một cái gì đó để xem xét. –

1

Trừ khi bạn áp dụng thuộc tính HandleProcessCorruptedStateExceptions cho một chức năng xử lý ngoại lệ, tất cả ngoại lệ 'không được xử lý bởi mã người dùng' đã bị bỏ qua để bạn có thể xử lý bất cứ điều gì ngoài quy trình hỏng ngoại lệ an toàn.

1

Tôi sẽ tham khảo lời khuyên từ bài viết sau.

.NET thiết kế Khung hướng dẫn quy tắc: Không Catch Exceptions Đó Bạn Không thể xử lý

http://www.codeproject.com/KB/cs/csmverrorhandling.aspx

Cũng từ bài viết tham khảo:

Bạn không bao giờ nên bắt System.Exception hoặc System.SystemException trong a khối catch

1

Bắt lỗi mà bạn mong đợi mã của bạn sẽ ném. Khi bạn đang sử dụng một API hoặc một phương pháp xem những gì ngoại lệ nó sẽ ném và chỉ bắt những người đó .. Bạn không nên làm cho một danh sách f trường hợp ngoại lệ và luôn luôn bắt những người ..

  • Đọc từ msdn google exception handling thực hành tốt nhất
  • không bao giờ bắt wit trường hợp ngoại lệ không đặc hiệu như ngoại lệ
Các vấn đề liên quan