"ArgumentException: элемент уже был добавлен" для хеш-таблицы

У меня странное поведение в одном из моих базовых методов веб-службы ASP.net. Прежде всего: это код, который работает годами, проблем с ним пока не сообщалось. Но в моих модульных тестах я дважды распознал эту проблему, поэтому сейчас я в замешательстве, если это только в моей разработке или это реальная проблема.

Вот мой фрагмент кода, где ошибка

System.ArgumentException: элемент уже был добавлен. Ключ в словаре: "6" Добавляемый ключ: "6"

произошло, когда _messages.Add называется:

public Message Add(GatewayMessageTypes type, string strMessage, CultureInfo language)
{
    var message = new Message(type, strMessage, language);

    int intCount = _messages.Count + 1;
    if (_messages.ContainsKey(intCount))
    {
        _messages.Remove(intCount);
    }

    _messages.Add(intCount, message);

    return message;
}

_messages определяется как:

public class MessageHandler
{
    private readonly Hashtable _messages = new Hashtable();

И этот MessageHandler используется во всех моих веб-сервисах, определенных в базовом классе.

public abstract class ServiceBase
{
    public MessageHandler MessageHandler { get; protected set; }

Это StackTrace:

   at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
   at System.Collections.Hashtable.Add(Object key, Object value)
   at GISGatewayCore.MessageHandler.Add(GatewayMessageTypes strType, String strMessage, CultureInfo language) in GISGateway\GISGatewayCore\MessageHandler.cs:line 69
   at GISGatewayCore.MessageHandler.AddAndLog(GatewayMessageTypes type, String strMessage, CultureInfo language) in GISGateway\GISGatewayCore\MessageHandler.cs:line 81
   at GISGateway.Services.GetClosestFacilityServices.<>c__DisplayClass4.<GetClosestFacilities>b__1(Object index) in GISGateway\GISGateway.Services\GetClosestFacilityServices.cs:line 592
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart(Object obj)

Правильно, в коллекции уже 6 записей, а номер 6 выглядит точно так же, как и новое сообщение, которое нужно добавить. Так в чем проблема?

  1. Не удалось удалить? Было ли это замедлить выполнение? Но код синхронно, не должно быть никаких проблем?
  2. Две разные записи с одинаковыми значениями? Я совершенно уверен, что это может быть исключено
  3. Существуют ли два параллельных процесса, использующих один и тот же код? Мои модульные тесты используют эту часть совместно, два моих теста используют одну и ту же конечную точку веб-службы. Но ни один из моих объектов не является статичным, так как это могло произойти?

1 ответ

Решение

Я понимаю вашу точку зрения, она должна работать синхронно. Однако попробуйте это и посмотрите, работает ли это:

public Message Add(GatewayMessageTypes type, string strMessage, CultureInfo language)
{
  lock(_messages)
  {
    var message = new Message(type, strMessage, language);

    int intCount = _messages.Count + 1;
    if (_messages.ContainsKey(intCount))
    {
        _messages.Remove(intCount);
    }

    _messages.Add(intCount, message);

    return message;
  }
}

Меня могут вызывать из двух источников в одной и той же "сессии", как вызовы ajax на контроллере.

Другие вопросы по тегам