1

複数スレッドのシナリオで辞書を実装しようとしています。シングルスレッドでは正常に動作しますが、複数スレッドのシナリオでは ArgumentNull Exception が発生しました。ロックを使用してみましたが、まだ運がありません。以下は、私の実装のコードの詳細です。

ここで、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(recipient.Name, out value1)、bcc.TryGetValue(recipient.Name,out value)、to.TryGetValue(recipient.Name, out value2) などの値を取得しようとしているときに発生します。

{System.ArgumentNullException: 値を null にすることはできません。パラメータ名: System.Collections.Generic.Dictionary 2.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 (クラスファイルパス)

4

2 に答える 2

1

この問題はおそらく次の原因で発生します。

finally
{
    NAR(recipient);
}

処理中に COM オブジェクトを解放しないでください。COM オブジェクトは、他のメールを処理している他のスレッドによって共有および使用される可能性があるためです。

すべてのスレッドがメールの処理を終了した場合にのみ、それらを解放してください。

たとえば、それらをリストで追跡し、最後にそれらを 1 つのバッチでリリースできます。

于 2013-11-11T11:12:56.913 に答える
0

メソッド名の上に [MethodImpl(MethodImplOptions.Synchronized)] を使用して解決策を見つけましたが、これにより遅くなります。

他の代替手段で可能でしょうか?

ありがとう

于 2013-11-11T12:20:14.817 に答える