이것은 흥미로운 질문입니다. 중복을 무시하는 차단 대기열을 요청한 사람은 이번이 처음입니다. 이상하게도 BCL에 이미있는 것과 같은 것을 찾을 수는 없습니다. BlockingCollection
은 중복이 감지되었을 때 실패 할 수 있다고 광고되는 TryAdd
메서드를 가진 기본 컬렉션으로 IProducerConsumerCollection
을 받아 들일 수 있기 때문에 이것이 이상하다고 말합니다. 문제는 중복을 방지하는 IProducerConsumerCollection
의 구체적인 구현이 없다는 것입니다. 적어도 우리는 우리 자신을 쓸 수 있습니다.
public class NoDuplicatesConcurrentQueue<T> : IProducerConsumerCollection<T>
{
// TODO: You will need to fully implement IProducerConsumerCollection.
private Queue<T> queue = new Queue<T>();
public bool TryAdd(T item)
{
lock (queue)
{
if (!queue.Contains(item))
{
queue.Enqueue(item);
return true;
}
return false;
}
}
public bool TryTake(out T item)
{
lock (queue)
{
item = null;
if (queue.Count > 0)
{
item = queue.Dequeue();
}
return item != null;
}
}
}
이제 우리는 중복을 허용하지 않는 우리의 IProducerConsumerCollection
을 가지고 우리는 다음과 같이 사용할 수 있습니다 :
public class Example
{
private BlockingCollection<object> queue = new BlockingCollection<object>(new NoDuplicatesConcurrentQueue<object>());
public Example()
{
new Thread(Consume).Start();
}
public void Produce(object item)
{
bool unique = queue.TryAdd(item);
}
private void Consume()
{
while (true)
{
object item = queue.Take();
}
}
}
당신은 NoDuplicatesConcurrentQueue
내 구현을 좋아하지 않을 수 있습니다. 당신은 확실히 ConcurrentQueue
또는 TPL 콜렉션이 제공하는 낮은 락 성능이 필요하다고 생각한다면 당신 자신을 구현할 수 있습니다.
업데이트 :
가 오늘 아침 코드를 테스트 할 수 있었다. 좋은 소식과 나쁜 소식이 있습니다. 좋은 소식은 이것이 기술적으로 효과가 있다는 것입니다. 나쁜 소식은 BlockingCollection.TryAdd
메서드가 기본 IProducerConsumerCollection.TryAdd
메서드에서 반환 값을 가로 채고 false
이 검색되면 예외를 throw하기 때문에이 작업을 수행하지 않으려는 것입니다. 네, 맞습니다. 기대했던대로 false
을 반환하지 않고 대신 예외를 생성합니다. 솔직히 말해서, 이것은 놀랍고 우습다. TryXXX 메서드의 요점은 예외를 던져서는 안된다는 것입니다. 나는 깊이 실망했다.브라이언 기드온이 업데이트후 언급 한주의뿐만 아니라
그런 방법이있는 경우 단일 원자 방법이어야합니다. Anothe 스레드가 TryPeek과 Add 사이에 추가 할 수 있기 때문에 두 발췌 부분을 구현할 때 결코 구현할 수 없습니다. 나는 네가 운이 없다고 생각해. 어쨌든 그런 능력이 필요한 이유는 무엇입니까? –
제 경우에는 다른 스레드가 trypeek와 add 사이에 추가해도 괜찮습니다. 나는 주로 스케줄러가 여러 스레드 (따라서 여러 프로듀서)에서 보고서 생성 트리거를 실행하는 안전 검사로 이것을 수행하고 있습니다. 어떤 이유로 든 스케줄러가 오작동하고 짧은 스팬에서 같은 트리거를 여러 번 실행하면 나는 단지 처리하고 싶다. 이해하고 주변에서 일할 수 있고 어떤 방식 으로든 다룰 수 있습니다. 이것을 다루는 우아한 방법이없는 것처럼 보입니다. – Gullu