2012-12-26 33 views
7

tôi có rò rỉ bộ nhớ khi sử dụng ConcurrentQueue:Memory rò rỉ với ConcurrentQueue

requestObject request = xxx; 

Item obj= new Item(); 
obj.MessageReceived += obj_MessageReceived; 
obj.Exited += obj_Exited; 

request.Key = obj.Key; 

obj.AddRequest(request); 

_queue.TryAdd(obj.Key, obj); 

Trong "thoát" gọi lại, tôi định đoạt tài nguyên:

void LiveSphere_Exited(string key) 
{ 
    Item instance; 

    _queue.TryRemove(key, out instance); 

    Task.Factory.StartNew(() => 
    { 
     var wait = new SpinWait(); 
     while (instance.MessageCount > 0) 
     { 
      wait.SpinOnce(); 
     } 
    }) 
    .ContinueWith((t) => 
    { 
     if (instance != null) 
     { 
      //Cleanup resources 
      instance.MessageReceived -= obj_MessageReceived; 
      instance.Exited -= obj_Exited; 
      instance.Dispose(); 
      instance = null; 
     } 
    }); 
} 

Khi tôi hồ sơ mã, tôi vẫn còn có một gốc tham chiếu "Item" đối tượng nhưng tôi không biết nơi tôi có thể xử lý ..., Phương pháp đã thoát được kích hoạt và _queue đã loại bỏ đối tượng "Item" khỏi hàng đợi.

Khi tôi đọc tài liệu, đồng thời sao chép tham chiếu vào hàng đợi.

Bạn có thể giúp tôi tìm ra nơi rò rỉ bộ nhớ không?

+5

Không chắc chắn nơi rò rỉ bộ nhớ của bạn. Đã có một rò rỉ bộ nhớ trong phiên bản .NET 4.0 của 'ConcurrentQueue', nhưng nó đã được sửa cho 4.5. Bạn có thể cân nhắc xem xét 'BlockingCollection', một trình bao bọc đẹp hơn nhiều xung quanh các bộ sưu tập đồng thời. Hành vi mặc định được sử dụng 'ConcurrentQueue' trong nội bộ. –

+0

Tôi ngần ngại gọi sự rò rỉ 'ConcurrentQueue' của .NET 4 - chủ yếu chỉ xảy ra nếu bạn không sử dụng nó nhiều (nó sẽ không đặt dữ liệu thành 'null' cho đến khi một số mục được xuất hiện) - trong trường hợp này , điểm của 'ConcurrentQueue' là gì? –

+0

Cảm ơn bạn Jim nhưng tôi đã có .NET 4.5 và tôi cần hàng đợi FIFO, bộ sưu tập chặn là FIFO? – dnx

Trả lời

6

Không giống như hàng đợi .NET chuẩn, gọi Dequeue() không loại bỏ tham chiếu đến đối tượng khỏi bộ sưu tập. Trong khi hành vi này đã thay đổi từ phiên bản 4.0 sang phiên bản 4.5 (tôi đã đọc, nhưng chưa thử nghiệm), nó không phải là lỗi, nhưng quyết định thiết kế có ý thức của nhóm khung làm một phần của thiết kế an toàn chỉ , bộ sưu tập đầy đủ.

This article có thêm thông tin, bao gồm giải pháp thay thế bằng cách sử dụng StrongBox để bao bọc các đối tượng đi vào ConcurrentQueue. Đó là một công việc thích hợp cho đến khi bạn có thể chuyển sang khung công tác 4.5.

+2

Tôi gọi đó là "lỗi thiết kế có ý thức", xem xét kết quả của nó. – hypersw

+0

Tôi đã thử cách tiếp cận StrongBox này nhưng chỉ làm chậm sự cố. bộ nhớ vẫn tăng lên khoảng 1.7GIG, sau đó ứng dụng có sự cố chậm trễ và sự cố. – user2520306

1

Tôi đã xem xét triển khai Hàng đợi đồng thời. Có những trường hợp khi hàng đợi sẽ giữ tham chiếu đến đối tượng sau khi Dequeue() được gọi.

Hàng đợi đồng thời sử dụng Phân đoạn để lưu trữ dữ liệu. Có nó là một phần của phương pháp TryRemove của phân khúc:

// If there is no other thread taking snapshot (GetEnumerator(), ToList(), etc), reset the deleted entry to null. 
// It is ok if after this conditional check m_numSnapshotTakers becomes > 0, because new snapshots won't include 
// the deleted entry at m_array[lowLocal]. 
if (m_source.m_numSnapshotTakers <= 0) 
{ 
    m_array[lowLocal] = default(T); //release the reference to the object. 
} 

Vì vậy, khi bạn có một chủ đề khác nhau mà liệt kê hàng đợi cùng một lúc bạn dequeue một đối tượng tham chiếu đến đối tượng sẽ không được thiết lập để null.

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