2011-09-19 36 views
0

我們在多線程環境中調用(線程安全)靜態方法,但需要將返回的錯誤消息添加到某種列表。.NET中<4所需的簡單線程安全列表對象

在.NET 4中,可以使用ConcurrentDictionary。但是,如果我需要在3.5中運行這個對象,那麼對於下面的allMessages對象,有什麼替代方法?

using (var mre = new ManualResetEvent(false)) 
{ 
    for (int i = 0; i < max1; i++) 
    { 
      ThreadPool.QueueUserWorkItem(st => 
      { 
      for (int j = 0; j < max2; j++) 
      { 
       string errorMsg; 
       // Call thread-safe static method 
       SomeStaticClass.SomeStaticMethod(out errorMsg); 

       // Need to collect all errorMsg in some kind of threadsafe list 
       // allMessages.Add(errorMsg); 

      } 
      if (Interlocked.Decrement(ref pending) == 0) mre.Set(); 
      }); 
    } 
    mre.WaitOne(); 
} 

的allMessages對象可以儘可能簡單 - 任何類型的列表會做到這一點能夠被填充在一個線程安全的方式串。

+2

如何使用正常的收集和鎖定? – CodesInChaos

+0

如果我使用任何私人對象thisLock = new Object();並鎖定(thisLock){allMessages.Add(errorMsg);},那就足夠了? – Olaf

+1

如果這是您訪問字典(包括閱讀和寫作)的唯一方式,那麼這應該就足夠了。 – CodesInChaos

回答

1

您可以編寫自己的ICollection<T>接口的實現,您只需將所有調用委託給類型爲List<T>的私有成員,即可爲每個訪問提供鎖定保護。

E.g.

public class LockedCollection<T> : ICollection<T> 
{ 
    private readonly object _lock = new object(); 
    private readonly List<T> _list = new List<T>(); 

    public void Add(T item) 
    { 
     lock (_lock) 
     { 
     _list.Add(item); 
     } 
    } 

    // other members ... 

} 

如果這是值得的「努力」(和代碼來維護),是你需要決定的問題。您可以用鎖/監視器保護您的呼叫到「普通」列表。

E.g.

  for (int j = 0; j < max2; j++) 
      { 
       string errorMsg; 
       // Call thread-safe static method 
       SomeStaticClass.SomeStaticMethod(out errorMsg); 

       lock (allMessageLock) // allMessagesLock is an "object", defined with the same lifetime (static- or instance-member) as "allMessages". 
       { 
        // Need to collect all errorMsg in some kind of threadsafe list 
        allMessages.Add(errorMsg); 
       } 
      } 
+0

謝謝。似乎沒有太多的努力。會試試看。 – Olaf

+0

只是擴大基督徒的答案,你可能想使用ReaderWriterLockSlim而不是一個簡單的鎖,以儘可能快地從集合中讀取,同時仍然確保寫入是線程sfae – Johnv2020