2014-04-28 27 views
6

我有一個應用程序,它具有存儲在Static concurrentbag中的對象列表。便攜式類庫中的ConcurrentBag替代方案

UI有一個計時器,它運行可以更新ConcurrentBag中的對象的方法。

只有一個線程(由計時器啓動)將嘗試更新這些對象。然而,這個線程將枚舉整個列表,然後更新項目。

同時這些對象可以被UI線程讀取。

ConcurrentBag正在爲我想要做的事情完美地工作。所有的業務邏輯都在一個單獨的項目中,我現在需要將所有內容移植到IOS和Android。我正在用Xamarin做這件事,所以我將業務邏輯轉換爲可移植類庫。

儘管我的目標似乎都支持ConcurrentBag,但當我嘗試在PCL中訪問它時,System.Collections.Concurrent不可用。即使我只針對.net 4.5及以上版本和windows應用商店(兩者我都使用ConcurrentBags)

如果還有另一種替代方案,或者我最好爲每個目標系統創建單獨的項目?

+0

哪個版本VS是你使用什麼,你選擇哪些PCL目標?如果我在VS2013 Update 2RC中選擇* .NET 4 *,* Windows(Store apps)8 *,* Xamarin.Android *和* Xamarin.iOS *,我可以在我的代碼中成功使用'ConcurrentBag'。只要你不瞄準* Windows Phone *或* Silverlight *,我認爲你在PCL中使用'ConcurrentBag'應該沒有問題。 –

+0

謝謝安德斯。我目前在更新1,所以我現在正在下載更新2,看看它是否有幫助。這是不是所有版本的Win手機都不起作用? – Oli

+0

我剛查過; System.Collections.Concurrent命名空間不包含在任何WP版本中,包括8.1。順便說一下,只要你避開WP/Silverlight目標,你就無法訪問VS 2013 Update 1上的'ConcurrentBag'?你是否已經仔細檢查了它在Update 1上不起作用,即使你的目標是.NET 4,Windows(Store)8,Xamarin.Android和Xamarin.iOS? –

回答

1

那麼,如果明顯不會工作,你有幾個選擇在這裏。首先,要反編譯ConcurrentBag並使用該代碼。其次,就是拿出一個替代品。這是我的估計,你在特定情況下,不一定需要的性能保證和ConcurrentBag的排序問題......所以,這是一個什麼會適合你的帳單工作示例:

namespace Naive 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 

    public class ThreadSafeCollectionNaive<T> 
    { 
     private readonly List<T> _list = new List<T>(); 
     private readonly object _criticalSection = new object(); 

     /// <summary> 
     /// This is consumed in the UI. This is O(N) 
     /// </summary> 
     public ReadOnlyCollection<T> GetContentsCopy() 
     { 
      lock (_criticalSection) 
      { 
       return new List<T>(_list).AsReadOnly(); 
      } 
     } 

     /// <summary> 
     /// This is a hacky way to handle updates, don't want to write lots of code 
     /// </summary> 
     public void Update(Action<List<T>> workToDoInTheList) 
     { 
      if (workToDoInTheList == null) throw new ArgumentNullException("workToDoInTheList"); 

      lock (_criticalSection) 
      { 
       workToDoInTheList.Invoke(_list); 
      } 
     } 

     public int Count 
     { 
      get 
      { 
       lock (_criticalSection) 
       { 
        return _list.Count; 
       } 
      } 
     } 

     // Add more members as you see fit 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var collectionNaive = new ThreadSafeCollectionNaive<string>(); 

      collectionNaive.Update((l) => l.AddRange(new []{"1", "2", "3"})); 

      collectionNaive.Update((l) => 
             { 
              for (int i = 0; i < l.Count; i++) 
              { 
               if (l[i] == "1") 
               { 
                l[i] = "15"; 
               } 
              } 
             }); 
     } 
    } 
}