2009-12-16 25 views
5

Tại sao SynchronizedCollection<T> không có được một khóa trên SyncObj trong việc thực hiện rõ ràng của IEnumerable.GetEnumerator()Tại sao SynchronizedCollection <T> không khóa trên IEnumerable.GetEnumerator()

IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.items.GetEnumerator(); 
    } 

thực hiện ngầm không có được một khóa trên SyncOb (xác nhận qua sự phản xạ).

Nó có thể là vấn đề trong vòng lặp foreach trên bộ sưu tập này. Một chủ đề có thể đã có được một khóa và người kia có thể thử đọc nó bằng cách sử dụng foreach?

Trả lời

1

Sửa đổi bộ sưu tập trong khi ai đó đang sử dụng trình lặp là một vi phạm đồng thời.

Lựa chọn thay thế của bạn là gì? Khóa bộ sưu tập khi trình vòng lặp được mua lại và không mở khóa cho đến khi trình vòng lặp bị hủy?

1

Tôi sẽ tiếp tục và nói rằng đây có thể là lỗi (ed: hoặc ít nhất là không nhất quán) trong quá trình triển khai. Trình phản chiếu hiển thị chính xác những gì bạn đang thấy, mà mọi triển khai rõ ràng khác đều khóa trên số SyncRoot được cung cấp, ngoại trừ IEnumerable.GetEnumerator().

Có lẽ bạn nên gửi vé tại Microsoft Connect.

Tôi tin rằng lý do tiềm ẩn GetEnumerator() phương pháp gọi lock là vì List<T>.GetEnumerator() tạo ra một Enumerator<T> mới mà dựa trên các lĩnh vực tin _version trong danh sách. Trong khi tôi đồng ý với các áp phích khác, rằng tôi không thấy việc sử dụng trong khóa cuộc gọi GetEnumerator(), nhưng kể từ khi các nhà xây dựng của Enumerator<T> dựa trên các lĩnh vực không an toàn, nó sẽ có ý nghĩa để khóa. Hoặc ít nhất là vẫn phù hợp với việc triển khai ngầm định.

4

Vì không có cách nào để lớp biết khi nào mã khách hàng được thực hiện bằng cách sử dụng trình lặp. Đó là một lý do mà tài liệu Thư viện MSDN trên các lớp System.Collection luôn cảnh báo rằng việc lặp lại một bộ sưu tập không phải là luồng an toàn.

Mặc dù chúng dường như đã quên đề cập đến trong bài viết cho SynchronizedCollection. Sự trớ trêu ...

+1

Tôi nghĩ điều mà anh ta đề cập đến là việc thực thi ngầm của GetEnumerator() thực sự gọi là khóa. – user7116

+0

Thật vậy. Silly, không có gì cần phải bị khóa. Tham chiếu danh sách nội bộ không thể thay đổi, chỉ nội dung của nó. Trình vòng lặp chỉ lưu trữ tham chiếu danh sách. –

+0

Tôi tin rằng nó nên bởi vì một cuộc gọi đến 'GetEnumerator()' cuối cùng tạo ra một mới 'Enumerator ' dựa trên trường 'List ._version'. – user7116

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