I have an application that has a list of objects stored in a static ConcurrentBag
.
The UI has a timer that runs methods that can update the objects in the ConcurrentBag
.
Only one thread (Started by the timer) will try to update these objects. However, this thread will enumerate through the list and then update the items as it goes.
At the same time these objects can be read by the UI thread.
ConcurrentBag
is working perfectly for what I want to do. All the business logic is in a separate project and I now need to port everything to iOS and Android. I'm doing this with Xamarin and so am converting the business logic into a Portable Class Library.
Although everything I'm targeting appears to support ConcurrentBag
, when I try to access it in a PCL, System.Collections.Concurrent
is not available. Even if I only target .net 4.5 and above + windows store apps (Both of which I have used ConcurrentBags
for)
Is there another alternative to ConcurrentBag
or am I better off just creating separate projects for each targeted system?
ConcurrentBag allows you to store objects in unordered way. Contrary to ConcurrentDictionary class, it allows you to store duplicate objects. ConcurrentBag allows multiple threads to store the objects. It is optimized for scenarios where same thread act as producer and consumer.
Bags are useful for storing objects when ordering doesn't matter, and unlike sets, bags support duplicates. ConcurrentBag<T> is a thread-safe bag implementation, optimized for scenarios where the same thread will be both producing and consuming data stored in the bag.
Well, if the obvious won't work, you have several options here. First, is to decompile ConcurrentBag and use that code. Second, is to come up with a replacement. It's my estimate that you in your specific case don't necessarily need the performance guarantees and ordering issues of a ConcurrentBag... So, this is a working example of what would fit your bill:
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";
}
}
});
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With