2013-07-02 28 views
10

Tôi có một chút mã mà làm việc như thế này trên một danh sách các đối tượng obj gọi ListofObjects:Thêm vào danh sách trong một vòng lặp Parallel.ForEach một cách threadsafe

List<SomeObject> NewListofObjects<SomeObject>(); 

Parallel.ForEach(ListofObjects, obj => 

//Do some operations here on obj to get a newobj 

NewListofObjects.Add(newobj); 

); 

Bây giờ tôi ra khỏi Parallel .ForMỗi vòng lặp, và tôi muốn thực hiện một thao tác trên NewListofObjects. Tuy nhiên, tôi nhận được lỗi này khi tôi cố gắng: "Đã cố gắng đọc hoặc ghi bộ nhớ được bảo vệ. Đây thường là dấu hiệu cho thấy bộ nhớ khác bị hỏng".

Đây có phải là vì phương pháp NewListofObjects.Add (newobj) của tôi không phải là luồng an toàn không? Nếu vậy, làm thế nào tôi có thể làm cho nó threadsafe?

+0

bạn đang làm gì bên trong (từ obj để đến newobj)? – terrybozzio

+0

Một loạt các hoạt động khó mô tả ... nhưng tất cả chúng đều là các biến cục bộ được tạo trong mỗi lần lặp của danh sách đối tượng. Bạn đang chính xác trong yêu cầu này mặc dù ... Tôi đã không loại trừ ra rằng tất cả các hoạt động tôi đang làm trên đối tượng cũng có thể là nguyên nhân gốc rễ của vấn đề cụ thể này. – Conor

Trả lời

26

Đây có phải vì phương pháp NewListofObjects.Add(newobj) của tôi không phải là chủ đề an toàn không?

Đúng. Nó không phải là chủ đề an toàn.

Bất kỳ thành viên nào không được đảm bảo an toàn chỉ.

Đó là từ MSDN tham chiếu đến List<T> (cuộn đến phần có tiêu đề "An toàn chủ đề").

Nếu có, làm thế nào tôi có thể làm cho chủ đề an toàn hơn?

Sử dụng bộ sưu tập đồng thời, như ConcurrentBag<T>. Lưu ý rằng bạn mất khả năng theo dõi thứ tự các mục đã được chèn vào.

+0

May mắn thay cho tôi thứ tự của các món hàng không quan trọng trong trường hợp của tôi. Cảm ơn! – Conor

+0

Tùy thuộc vào nhu cầu của bạn, bạn có thể sử dụng ConcurrentBag để xử lý rồi thực hiện một cái gì đó như 'var list = bag.OrderBy (p => p.SomeCondition) .ToList();' Điều đó có thể hoạt động tốt hơn so với khóa xung quanh mọi danh sách thêm vào. –

14

Bạn có thể sử dụng khối locking như mã sau để chèn các mục vào danh sách của mình theo cách an toàn.

var sync = new object(); 
var myNewList = new List<SomeObject>(); 
Parallel.ForEach(myListOfSomethings, a => 
    { 
     // Some other code... 
     var someObj = new SomeObject(); 
     // More other code... 
     lock(sync) 
     { 
      myNewList.Add(someObj); 
     } 
     // Even more code... 
    }); 
+1

Tôi ước tôi có thể đánh dấu nhiều câu trả lời là chính xác vì điều này cũng sẽ giải quyết vấn đề. Cảm ơn! – Conor

+1

Không sao cả! Giải pháp này bảo tồn thứ tự của các mục được thêm vào quá, nhưng trong trường hợp của bạn nó hoạt động ra một trong hai cách. Phương pháp của Jason có hiệu suất tốt hơn. – ajawad987

+0

Có lý do nào để không khóa myNewList không? – Alex

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