"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 ответ
Я понимаю вашу точку зрения, она должна работать синхронно. Однако попробуйте это и посмотрите, работает ли это:
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 на контроллере.