2010-02-11 36 views
6

Có bất kỳ điểm nào trong việc theo dõi trường cổ điển bool disposed trên một loại an toàn theo chủ đề khác với mục đích ném ObjectDisposedException vào đầu tất cả các phương pháp tiếp xúc chính không?IDisposable, ObjectDisposedException, và các loại an toàn

Tôi đã nhìn thấy mẫu này được đề xuất ở một vài nơi trực tuyến nhưng tôi không chắc liệu các tác giả có đang sử dụng nó một cách chính xác hay không, vì vậy câu hỏi này giả định rằng chúng là.

Trong trường hợp như vậy, có vẻ như cách duy nhất để đảm bảo rằng điều kiện disposed là đúng ngoài đánh giá của điều kiện là sử dụng cơ chế đồng bộ hóa như khóa() trên toàn bộ cơ thể của mỗi thành viên được tiếp xúc bao gồm Vứt bỏ (bool). Điều này sẽ không làm cho loại có hiệu quả đơn luồng một lần nữa? Và nếu điều này là đúng, thì sẽ không có điểm trong việc sử dụng nó, và do đó bạn không thể dựa vào cơ chế ObjectDisposedException trong một số triển khai IDisposable - vậy thì tại sao chúng ta sẽ sử dụng cơ chế này nếu nó không phải là ' t cần thiết?

====

Tôi đoán IDisposable và ObjectDisposedException chỉ không đi cùng nhau với nhiều loại thread-safe.

+0

Xem thêm: http://stackoverflow.com/questions/170028/how-would-you-simplfy-entering-and-exiting-a-readerwriterlock –

Trả lời

4

Có lẽ cách hiệu quả hơn để tạo đối tượng threadsafe không bị xử lý trong khi phương thức đang chạy là sử dụng ReaderWriterLockSlim. Có tất cả các phương pháp công cộng có được một khóa đọc trong khi thực hiện và phát hành nó khi chúng được thực hiện. Có Dispose lấy khóa nhà văn. Nó sẽ đợi cho đến khi tất cả các phương pháp khác được thực hiện trước khi nó có được nó viết khóa. Sau đó nó đặt isDisposed bên trong khóa ghi mà nó độc quyền nắm giữ. Mọi cuộc gọi đến phương thức công khai sau Dispose được thực hiện có thể xem isDisposed và ném ObjectDisposedException.

ReaderWriterLockSlim

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

+0

Ý tưởng hay. Có một mẫu? Không tìm tài liệu trên ReaderWriterSlimLock. Đây có phải là thứ bạn đã từng thấy trước đây hay thứ gì đó mà bạn vừa suy nghĩ không? –

+0

Chỉ cần động não, nhưng tôi nghĩ rằng nó sẽ làm việc tốt cho yêu cầu của bạn. Tôi đã viết sai chính tả trong câu trả lời ban đầu của tôi, đó là 'ReaderWriterLockSlim'. Tôi đã thêm một liên kết đến tài liệu MSDN. –

+0

Trên thực tế, hầu hết các công trình, ngoại trừ FXcop đó chỉ ra rằng ReaderWriterLockSlim triển khai IDisposable và nên được xử lý cùng với phần còn lại của tài nguyên của đối tượng. Vì vậy, một khi vứt bỏ được gọi là, tôi sẽ không còn có thể có được một khóa đọc để kiểm tra nếu đối tượng đã được xử lý hay không. –

3

Nếu hành vi của đối tượng của bạn sẽ khác nếu nó đã được xử lý, và nếu nó có khả năng nó sẽ được sử dụng sau khi nó được xử lý, sau đó bạn cần phải giữ theo dõi điều này. Tốt hơn là hãy ném ObjectDisposedException hơn là ném bất kỳ ngoại lệ ngẫu nhiên nào sẽ xảy ra nếu đối tượng đã được xử lý và bạn không kiểm tra trước.

+0

Có, nhưng câu hỏi này là làm thế nào để ném một ObjectDisposedException một cách chắc chắn trong một kịch bản đa luồng. –

+0

@ Jason: trong trường hợp đó, hãy chỉnh sửa câu hỏi của bạn để nói như vậy. –

0

Cho rằng boolean "được xử lý" chỉ được cập nhật ở một nơi và đó là lỗi trong trình gọi của bạn để sử dụng đối tượng sau khi chúng được gọi là Xử lý.

Tôi nghĩ rằng nó đủ tốt để ném ObjectDisposedException "hầu hết thời gian" sau khi Vứt bỏ đã được gọi. Tôi thấy ObjectDisposedException như là một trình trợ giúp gỡ lỗi không phải là điều mà người gọi nên được bắt.

0

Nếu có khả năng một phương thức được gọi trong khi đối tượng được xử lý, ngữ nghĩa của phương thức nên được xác định theo cách gọi nó trên đối tượng được xử lý sẽ không gây ra vấn đề gì. Trong trường hợp có thể có hoặc không có vấn đề gì, bạn nên sử dụng mẫu "try/do". Nếu Microsoft đã tuân theo nguyên tắc này với Control.BeginInvoke, sẽ có cả một "Control.BeginInvoke" và một "Control.TryBeginInvoke"; sau này sẽ được xác định rõ ràng là trả về false và không làm gì nếu điều khiển được xử lý trước khi hành động được enqueued (lưu ý rằng Control.BeginInvoke trả về true sẽ không đảm bảo rằng điều khiển sẽ không được xử lý trước khi hành động thực sự chạy).Mô hình này sẽ rất hữu ích trong những thứ như kịch bản hiển thị-cập nhật: nếu một điều khiển không được xử lý, tôi muốn thường xuyên cập nhật của nó để chạy; nếu nó được xử lý trước khi chạy thường xuyên cập nhật, tuy nhiên, bản cập nhật sẽ trở thành tranh luận và thất bại của nó để chạy sẽ khó có thể là một vấn đề.

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