Trong khi tôi làm như tài liệu, tôi có xu hướng để xác minh điều này với một chương trình nhỏ khi nghi ngờ hoặc tôi cảm thấy rằng tôi có thể giả định quá nhiều.
Mã sau đây xác minh rằng bạn thực sự có thể liệt kê các bộ sưu tập giá trị một cách an toàn trong khi thêm hoặc xóa khóa khỏi một chuỗi riêng biệt với chuỗi liệt kê. Điều này sẽ không khiến bộ sưu tập thông thường bị sửa đổi ngoại lệ. Cụ thể hơn, sau đây là một vài trường hợp thử nghiệm
Trường hợp 1: Tiến hành thống kê các giá trị và xóa một phím
Nếu bạn làm theo trình tự sau đây:
- bắt đầu liệt kê bộ sưu tập giá trị từ một chủ đề
- xóa khóa khỏi một chuỗi khác mà chúng tôi chưa liệt kê chưa
- Tiếp tục liệt kê trên chuỗi gốc
Hành vi được quan sát là khóa đã xóa sẽ thực sự được liệt kê vì nó tồn tại trong bộ sưu tập giá trị khi chúng tôi bắt đầu đếm. Không có ngoại lệ sẽ được nâng lên.
Trường hợp 2: Tiến hành thống kê các giá trị và thêm một chìa khóa
- bắt đầu liệt kê bộ sưu tập giá trị từ một sợi
- thêm một khóa mới từ một thread khác nhau mà chúng ta chưa liệt kê chưa
- Tiếp tục liệt kê trên chủ đề ban đầu
Hành vi được quan sát là khóa được thêm sẽ không được liệt kê vì nó d id không tồn tại trong bộ sưu tập giá trị khi chúng tôi bắt đầu liệt kê nó. Không có ngoại lệ sẽ được nâng lên cho dù chúng tôi sử dụng TryAdd hoặc thêm bằng cách chỉ định trực tiếp vào từ điển tức là từ điển [key] = giá trị.
Mã mẫu
Dưới đây là chương trình mẫu đó chứng tỏ cả hai trường hợp:
ConcurrentDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();
// Seed the dictionary with some arbitrary values;
for (int i = 0; i < 30; i++)
{
dictionary.TryAdd(i, i);
}
// Reader thread - Enumerate the Values collection
Task.Factory.StartNew(
() =>
{
foreach (var item in dictionary.Values)
{
Console.WriteLine("Item {0}: count: {1}", item, dictionary.Count);
Thread.Sleep(20);
}
}
);
// writer thread - Modify dictionary by adding new items and removing existing ones from the end
Task.Factory.StartNew(
() =>
{
for (int i = 29; i >= 0; i--)
{
Thread.Sleep(10);
//Remove an existing entry
int removedValue;
if (dictionary.TryRemove(i, out removedValue))
Console.WriteLine("Removed item {0}", removedValue);
else
Console.WriteLine("Did not remove item {0}", i);
int iVal = 50 + i*2;
dictionary[iVal] = iVal;
Thread.Sleep(10);
iVal++;
dictionary.TryAdd(iVal, iVal);
}
}
);
Console.ReadKey();
Và đây là đầu ra trong chế độ phát hành:
Các điều tra viên hoạt động khác với Khóa và Giá trị pr operties. Trong khi chúng cung cấp ảnh chụp nhanh thời gian trong từ điển, nội dung được trả về bởi ['GetEnumerator'] (https://msdn.microsoft.com/en-us/library/dd287131.aspx) (cũng được sử dụng trong Truy vấn LINQ sử dụng từ điển làm nguồn) chứa các sửa đổi được thực hiện cho từ điển sau khi 'GetEnumerator' được gọi. –