Чи не вдається ConcurrentDictionary.TryAdd?


76

Це більше академічне питання ... але чи не може ConcurrentDictionary.TryAdd зазнати невдачі? І якщо так, то в яких випадках і чому?


1
На сьогодні це питання досить розпливчасте. На сторінці MSDN зафіксовано кілька причин, виняткових та інших (як уже зазначалося у відповідях).
Крістіан.

15
так, і документація MSDN відома своєю ясністю та бездоганністю
Дейв Лоуренс,

4
Ну, це здається досить чітким і бездоганним для інших відповідей.
Крістіан.

13
MSDN може бути не ідеальним, але я ще не працював з мовою, яка краще документована, ніж C # /. NET. З іншими мовами частіше за все я замислююся, наскільки кращою була б документація, якби вона більше нагадувала MSDN.
Michael Richardson

2
NET 4.0 У нас є випадок, коли програма веб-API ASP.NET періодично не виконує всі наступні виклики TryAdd за допомогою IndexOutOfRangeException. Це відбувається на одному сервері в пулі, доки сервер не буде витягнутий і пул програм не скинеться. Ми ще не знайшли відповідного способу вирішення цього питання.
Девід Норт

Відповіді:


110

Так, може, ось умови ( від msdn ):

  • ArgumentNullException - коли ключ є нульовим посиланням
  • OverflowException - коли досягнуто максимальної кількості елементів
  • Він повертає значення false, якщо елемент з тим самим ключем уже існує

Повторюючи, це нічого спільного з паралелізмом. Якщо ви турбуєтесь про те, що дві нитки вставляють елемент одночасно, може статися таке:

  • Обидві вставки чудово працюють, якщо клавіші різні.
  • Одна вставка працює нормально і повертає true, інша вставка не працює (за винятком) і повертає false. Це трапляється, якщо дві нитки намагаються вставити предмет з однаковим ключем і в основному виграє лише одна, а інша - програє.

4
Гаразд ... так що нічого спільного з одночасним доступом .. він просто виконує ті самі перевірки, які мали б робити зі стандартним словником.
Дейв Лоуренс,

1
Так, внутрішньо він використовує обертання процесора, що дозволяє проводити кілька одночасних з'єднань.
oleksii

Дякую .. Я приймаю вашу відповідь як найбільш конструктивну. Ми тут налагоджуємо досить невловимий баг і виключаємо можливі джерела по черзі. Я можу виключити функцію TryAdd, виходячи з того, що ви внесли (хоча я все одно додаю додаткові журнали, якщо їх не вдасться додати)
Дейв Лоуренс,

2
@deveL зазвичай дуже важко налагоджувати багатопотокові програми. Але я би довірився System.Collections.Concurrentпростору імен, оскільки він був широко перевірений. Також погляньте на паралельну нуніт . Я ніколи з цим не працював, але, схоже, це стосується питання паралельного тестування модульного коду. Для цього повинні бути інші фреймворки, якщо ви не використовуєте NUnit.
oleksii

1
Повторна спроба @parlament дала б той самий результат, зробивши це безглуздим. Повернення false не означає "мені не вдалося вставити елемент" це більше "щось інше вже вставлено елемент"
Джим Вольф,

8

Звичайно, це можливо. Якщо ключ уже існує, метод поверне false.

Посилання: http://msdn.microsoft.com/en-us/library/dd267291.aspx

Тип поверненого значення: System.Boolean true, якщо пара ключ / значення була додана до ConcurrentDictionary успішно. Якщо ключ вже існує, цей метод повертає значення false.


Ну ... це даність. Це єдиний випадок, коли він може зазнати невдачі?
Дейв Лоуренс,

@daveL - так, коли трапляються винятки ... див. відповідь Олексія.
Chris Gessler

Дякую за вашу допомогу .. Я поставив вам +1
Дейв Лоуренс

1
Враховуючи те, що заявлений намір функції полягає в тому, щоб повідомити вам, чи елемент був доданий чи вже був, я не думаю, що повернення false є помилкою.
Найл Коннотон

2

Це не вдасться, коли ключ вже існує у словнику.

Якщо значення неможливо додати, оскільки у вас закінчилася пам’ять, ви отримаєте замість цього виняток.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.