Làm thế nào để xóa ConcurrentBag
? nó không có bất kỳ phương thức nào giống như Clear
hoặc RemoveAll
...
Câu trả lời:
Mặc dù nó có thể không hoàn toàn rõ ràng do điều kiện chủng tộc tiềm ẩn, nhưng điều này là đủ:
while (!myBag.IsEmpty)
{
myBag.TryTake(out T _);
}
Cập nhật 10/03/2017: Như @Lou đã chỉ ra một cách chính xác, nhiệm vụ là nguyên tử. Trong trường hợp này, việc tạo ra ConcurrentBag
will không phải là nguyên tử, nhưng việc đặt tham chiếu đó vào biến sẽ là nguyên tử - vì vậy việc khóa hoặc Interlocked.Exchange
xung quanh nó là không bắt buộc.
Một số bài đọc thêm:
phép gán tham chiếu là nguyên tử, vậy tại sao cần Interlocked.Exchange (ref Object, Object)?
Một chỉ định tham chiếu có an toàn không?
Bạn luôn có thể khóa quyền truy cập vào chính chiếc túi và tạo một phiên bản mới của nó. Sau đó, các vật phẩm trong túi sẽ có thể sử dụng được đối với GC nếu không có thứ gì khác đang giữ chúng:
lock (something)
{
bag = new ConcurrentBag();
}
Hoặc như Lukazoid chỉ ra:
var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Tuy nhiên, cách dễ dàng để phân loại nội dung, điều này giả định rằng bất cứ khi nào một mục muốn truy cập, nó cũng sẽ bị khóa - điều này có thể tốn kém và có thể phủ nhận việc điều chỉnh hiệu suất đã đi vào ConcurrentBag
chính nó.
Nếu bạn biết rằng không có gì khác sẽ truy cập vào túi vào lúc này, hãy canh cánh và cầu nguyện nó và đừng khóa :-)
bag = new
với sự trừng phạt?
Interlocked.Exchange
có thể tốt hơn một ổ khóa
Interlocked.Exchange
hoạt động nếu một sợi khác được thêm vào túi tại thời điểm trao đổi? Điều đó Add
có bị khóa trong thời gian Exchange
?
Interlocked.Exchange
là dự phòng ở đây (và không cung cấp an toàn cho luồng).
Câu trả lời đã chọn là một giải pháp tốt, vì vậy tôi đang thêm cách giải quyết của riêng mình.
Giải pháp của tôi là xem xét tất cả các bộ sưu tập có sẵn trong không gian tên System.Collections.Concurrent để tìm một vùng mà việc xóa tất cả các phần tử khỏi bộ sưu tập là không đáng kể.
Lớp ConcurrentStack có phương thức Clear () xóa tất cả các phần tử khỏi tập hợp. Trên thực tế, đó là bộ sưu tập duy nhất trong không gian tên (hiện tại) làm được điều đó. Có, bạn phải Push(T element)
thay thế Add(T element)
, nhưng thành thật mà nói điều đó đáng để tiết kiệm thời gian.
ConcurrentBag
? Tôi không thể thấy bất kỳ thuộc tính hoặc phương thức gốc nào để làm điều đó. Các Contains
không được tính. Nó là một phương pháp mở rộng cho IEnumerable
các s chung chung và nó là bất cứ thứ gì nhưng hiệu quả.
Theo tinh thần của các giải pháp thay thế .. ConcurrentDictionary<T, bool>
có một Clear nguyên tử, nhưng cũng cho phép bạn nhanh chóng kiểm tra xem có tồn tại một khóa hay không. Tất nhiên, 'nhanh chóng' là một thuật ngữ tương đối, nhưng tùy thuộc vào cách sử dụng của bạn, nó có thể nhanh hơn so với việc liệt kê một ngăn xếp lớn.
Kể từ .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0, có một Clear()
phương pháp trên ConcurrentBag<T>
. Xem: ConcurrentBag.Clear .