Как реализовать словарь в многопоточном сценарии, чтобы избежать ArgumentNull Exception?
Я пытаюсь реализовать словарь в многопоточном сценарии. В одном потоке он работает нормально, однако в многопоточном сценарии я получил исключение ArgumentNull. Я пытался использовать замок до сих пор не повезло. Ниже приведены детали кода моей реализации.
Здесь IRDOMail oItem является классом от Exchangeserver WebService.
var bcc = new Dictionary<string, bool>(7, StringComparer.InvariantCultureIgnoreCase);
var cc = new Dictionary<string, bool>(7, StringComparer.InvariantCultureIgnoreCase);
var to = new Dictionary<string, bool>(7, StringComparer.InvariantCultureIgnoreCase);
if (oItem.BCC != null)
{
foreach (var itemBcc in oItem.BCC.Split(';'))
if (!string.IsNullOrEmpty(itemBcc.Trim()))
{
lock (bcc)
bcc[itemBcc.Trim()] = true;
}
}
if (oItem.CC != null)
{
foreach (var itemCc in oItem.CC.Split(';'))
if (!string.IsNullOrEmpty(itemCc.Trim()))
{
lock (cc)
cc[itemCc.Trim()] = true;
}
}
if (oItem.To != null)
{
foreach (var itemTo in oItem.To.Split(';'))
if (!string.IsNullOrEmpty(itemTo.Trim()))
{
lock(to)
to[itemTo.Trim()] = true;
}
}
var bccEntries = new List<string>(bcc.Count);
var ccEntries = new List<string>(cc.Count);
var toEntries = new List<string>(to.Count);
RDORecipients recipients = null;
RDORecipient recipient = null;
try
{
recipients = oItem.Recipients;
for (int i = 1; i <= recipients.Count; i++ )
{
try
{
recipient = recipients[i];
if (recipient == null || recipient.EntryID == null)
continue;
if (string.IsNullOrEmpty(recipient.Name))
continue;
lock (bcc)
{
bool value;
if (bcc.TryGetValue(recipient.Name,out value))
bccEntries.Add(recipient.EntryID);
}
lock (cc)
{
bool value1;
if (cc.TryGetValue(recipient.Name, out value1))
ccEntries.Add(recipient.EntryID);
}
lock (to)
{
bool value2;
if (to.TryGetValue(recipient.Name, out value2))
toEntries.Add(recipient.EntryID);
}
}
finally
{
NAR(recipient);
}
}
}
finally
{
NAR(recipients);
recipients = null;
}
Исключение: -
Это исключение возникает при попытке получить значение, т.е. cc.TryGetValue (получатель.Имя, выходное значение1), bcc.TryGetValue(получатель.Имя, выходное значение) и to.TryGetValue(получатель.Name, выходное значение2)
{System.ArgumentNullException: значение не может быть нулевым. Имя параметра: ключ в System.ThrowHelper.ThrowArgumentNullException(аргумент ExceptionArgument) в System.Collections.Generic.Dictionary2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary
2.TryGetValue (ключ TKey, TValue& значение) в ABC.Common.Collection.SynchronizedDictionary`2.TryGetValue(ключ TKey, TValue& значение) в (Путь к файлу класса)
2 ответа
Проблема, вероятно, исходит от:
finally
{
NAR(recipient);
}
Вы не должны освобождать COM-объекты во время обработки, потому что они могут быть общими и использоваться другими потоками, работающими с другими письмами.
Отпустите их, только когда все потоки закончили обрабатывать почту.
Вы можете отслеживать их в списке, например, и в конце выпустить их в одной партии.
Я нашел решение, используя [MethodImpl(MethodImplOptions.Synchronized)] над именем метода, но это делает медленнее.
Возможно ли это с другими альтернативами?
Спасибо Бинод