2010-10-24 41 views
6

Tôi cố gắng để thực hiện đoạn mã sau và tôi tiếp tục nhận được một Index ra khỏi phạm vi ngoại lệ khi cố gắng gán giá trị mảng vào danh sách: -Index ra khỏi phạm vi ngoại lệ khi sử dụng song song cho vòng lặp

 int[] array = new int[1000000]; 
     for (int i = 0; i < array.Length; i++) 
     { 
      array[i] = i; 
     } 

     List<int> list = new List<int>(); 
     Parallel.For(0, array.Length, i => list.Add(array[i])); 

Am Tôi làm gì sai ở đây? Tôi hiểu rằng quá trình này không có thứ tự/không đồng bộ, nhưng tại sao "i" nhận được các giá trị cao hơn giá trị của "array.Length"?

Trả lời

15

Vấn đề là bạn không thể gọi List.Add() đồng thời trên nhiều chuỗi. Nếu bạn cần bộ sưu tập chủ đề an toàn, hãy xem không gian tên System.Collections.Concurrent.

Nếu bạn đột nhập vào trình gỡ lỗi khi bạn nhận được một ngoại lệ, bạn sẽ thấy rằng ikhông lớn hơn array.Length, nhưng thay vào đó một sức mạnh của 2 đó là đáng kể ít hơn array.Length. Điều gì xảy ra là List bắt đầu với một mảng trống của một cái gì đó giống như 4 yếu tố. Bất cứ khi nào bạn thêm một phần tử vào một danh sách có mảng đầy, nó tạo ra một mảng dài gấp đôi chiều dài của mảng cũ, sao chép các phần tử cũ vào nó, và lưu trữ mảng mới.

Bây giờ, hãy nói rằng danh sách của bạn có tối đa 31 phần tử (có nghĩa là nó có không gian cho một phần tử khác) và hai chuỗi sẽ cố gắng thêm phần tử thứ 32. Cả hai đều sẽ thực thi mã như thế này:

if (_size == _items.Length) 
{ 
    EnsureCapacity(_size + 1); 
} 
_items[_size++] = item; 

Đầu tiên họ cả hai sẽ thấy rằng _size (31) không phải là _items.Length (32), vì vậy cả hai đều thực hiện _size++. Chủ đề đầu tiên sẽ nhận được 31 (chỉ số chính xác của phần tử thứ 32) và thay đổi _size thành 32. Chuỗi thứ hai sẽ nhận được 32 và cố gắng lập chỉ mục _items[32], cung cấp cho bạn ngoại lệ của bạn vì nó đang cố gắng truy cập vào phần tử thứ 33 của 32 mảng phần tử.

+2

Câu trả lời hay. Tôi ước tôi có thể bỏ phiếu lên gấp đôi. Tôi sẽ tham khảo điều này trên bài đăng blog tiếp theo của tôi; Tôi hy vọng bạn không nhớ. –

+0

+1 câu trả lời tuyệt vời tuyệt vời, cảm ơn gabe! – andy

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