1

I am trying to implement the dictionary in multiple thread scenario. In single thread it works fine however in multiple thread scenario i got the ArgumentNull Exception. I have tried using the lock still no luck. Below is the code details of my implementation.

Here IRDOMail oItem is the class from 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;
                    }

Exception: -

These exception occours while Trying to Get value ie cc.TryGetValue(recipient.Name, out value1), bcc.TryGetValue(recipient.Name,out value) and to.TryGetValue(recipient.Name, out value2)

{System.ArgumentNullException: Value cannot be null. Parameter name: key at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Collections.Generic.Dictionary2.FindEntry(TKey key) at System.Collections.Generic.Dictionary2.TryGetValue(TKey key, TValue& value) at ABC.Common.Collection.SynchronizedDictionary`2.TryGetValue(TKey key, TValue& value) in (Class File Path)

Binod
  • 313
  • 1
  • 2
  • 12

2 Answers2

1

The issue probably comes from:

finally
{
    NAR(recipient);
}

You should not release COM objects during processing because they may be shared and used by other threads working on other mails.

Release them only when all the threads have finished to process the mails.

You can keep track of them in a list for example, and at the end release them in a single batch.

Pragmateek
  • 13,174
  • 9
  • 74
  • 108
0

I have found the solution using [MethodImpl(MethodImplOptions.Synchronized)] above the method name but this makes slower.

Could it be possible with other alternatives?

Thanks Beenodh

Binod
  • 313
  • 1
  • 2
  • 12
  • This is not a solution as it completely nullifies the use of multi-threading. `Synchronized` has the same semantics as in Java: it instructs the CLR to synchronize all the access to the method, so only one thread at a time can run it. – Pragmateek Nov 11 '13 at 23:26
  • Assign the recipient.Name to some variable as recipientName = recipient.Name and use it as below. if (bcc.TryGetValue(recipientName,out value)) follow same for bcc and to also. – Binod Nov 14 '13 at 11:47