Разница между Take/TryTake и Add/TryAdd для блокирующей коллекции
Я пытался разобраться с коллекцией блокировок, и я наткнулся на Take()
а также TryTake()
также Add()
а также TryAdd()
Я понимаю, что если нет вещей, которые можно взять, Take()
будет ждать, пока элемент будет добавлен, аналогично Add()
если коллекция достигла максимального предела, она будет ждать, пока элемент не будет удален.
Согласно статье Джошефа Албахари о параллельном программировании
"Add и TryAdd могут блокироваться, если размер коллекции ограничен; блоки Take и TryTake, пока коллекция пуста".
Так Take()
а также TryTake()
оба ожидают добавления элемента. Итак, если мы не предоставляем токен тайм-аута или отмены, какая разница между Take()
а также TryTake()
не должен TryTake()
return false
и сразу не ждать? и то же самое для TryAdd()
?
2 ответа
TryTake
не ждет, сразу возвращается false
если в коллекции ничего нет. Take
будет ждать предмета.
TryTake:
Если коллекция пуста, этот метод немедленно возвращает false.
Возьмите:
Вызов Take может блокироваться до тех пор, пока предмет не будет доступен для удаления.
Take
будет сигнализировать о завершении очереди, бросая InvalidOperationException
, Это делает отладку немного сложной, если у вас есть настроенная вкладка исключений для перехваченных исключений.
Из-за этого я пытался использовать TryTake
, Оказывается, что BlockingCollection<T>.Take
на самом деле использует TryTake
, но с бесконечным таймаутом. Поэтому вместо того, чтобы писать это:
while (!queue.IsCompleted)
{
object obj;
try
{
obj = queue.Take();
}
catch (InvalidOperationException)
{
continue;
}
// Do something with obj.
}
Ты можешь использовать TryTake
следующее:
while (!queue.IsCompleted)
{
if (!queue.TryTake(out var obj, Timeout.InfiniteTimeSpan))
continue;
// Do something with obj.
}
Делает код намного чище и не бросает InvalidOperationException
,
Я наткнулся на этот вопрос и думаю, что этот документ Microsoft действительно полезен для понимания того, что происходит за наукой.
Если элемент отсутствует, достигнута максимальная емкость ограниченной коллекции или истек период ожидания, то операция TryAdd или TryTake возвращает false. Это позволяет потоку некоторое время выполнять другую полезную работу, а затем повторить попытку позже, либо получить новый элемент, либо попытаться добавить тот же элемент, который не мог быть добавлен ранее.
Как добавлять и брать элементы по отдельности из коллекции BlockingCollection