Giống như các câu trả lời khác được đề cập, cập nhật biến số sum
từ nhiều luồng (đó là những gì mà Parallel.ForEach thực hiện) không phải là thao tác an toàn theo luồng. Bản sửa lỗi nhỏ nhặt có được khóa trước khi thực hiện cập nhật sẽ khắc phục sự cố rằng vấn đề.
double sum = 0.0;
Parallel.ForEach(myCollection, arg =>
{
lock (myCollection)
{
sum += ComplicatedFunction(arg);
}
});
Tuy nhiên, điều đó lại giới thiệu một vấn đề khác. Kể từ khi khóa được mua lại trên mỗi lần lặp lại thì điều đó có nghĩa là việc thực thi mỗi lần lặp lại sẽ được tuần tự một cách hiệu quả. Nói cách khác, sẽ tốt hơn nếu chỉ sử dụng vòng lặp cũ foreach
cũ.
Bây giờ, mánh khóe trong việc có được quyền này là phân chia vấn đề trong các chucks riêng biệt và độc lập. May mắn thay đó là siêu dễ thực hiện khi tất cả những gì bạn muốn làm là tổng kết quả của các phép lặp bởi vì phép tính tổng là giao hoán và kết hợp và bởi vì các kết quả trung gian của các phép lặp là độc lập.
Vì vậy, đây là cách bạn làm điều đó.
double sum = 0.0;
Parallel.ForEach(myCollection,
() => // Initializer
{
return 0D;
},
(item, state, subtotal) => // Loop body
{
return subtotal += ComplicatedFunction(item);
},
(subtotal) => // Accumulator
{
lock (myCollection)
{
sum += subtotal;
}
});
Nguồn
2010-07-30 03:55:32
Xem [ tăng một giá trị đếm bên ngoài phạm vi parallel.foreach ] (http://stackoverflow.com/questions/2394447/increment-a-count-value-outside-parallel-foreach-scope). Về cơ bản, bạn có thể sử dụng [Interlocked] (http://msdn.microsoft.com/en-us/library/55dzx06b.aspx) nếu bạn cần, nhưng tốt hơn nên tránh tác dụng phụ nếu có thể. –