The*_*ght 23 c# generics multithreading list
我有一个通用列表如下
public static readonly List<Customer> Customers = new List<Customer>();
Run Code Online (Sandbox Code Playgroud)
我正在使用以下方法:
.Add
.Find
.FirstOrDefault
Run Code Online (Sandbox Code Playgroud)
最后2个是LINQ扩展.
我需要使这个线程安全的能够运行容器类的多个实例.
怎么实现呢?
Jar*_*Par 42
如果这些是您正在使用的唯一函数,List<T>那么最简单的方法是编写一个快速包装器,将访问与a同步lock
class MyList<T> {
private List<T> _list = new List<T>();
private object _sync = new object();
public void Add(T value) {
lock (_sync) {
_list.Add(value);
}
}
public bool Find(Predicate<T> predicate) {
lock (_sync) {
return _list.Find(predicate);
}
}
public T FirstOrDefault() {
lock (_sync) {
return _list.FirstOrDefault();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我强烈推荐新类型+私有锁对象的方法.对于继承你的代码的下一个人来说,实际意图是什么让它变得更加明显.
另请注意,.Net 4.0引入了一组新的集合,专门用于从多个线程中使用.如果其中一个满足您的需求,我强烈建议您使用它自己滚动.
ConcurrentStack<T>ConcurrentQueue<T>Alb*_*reo 10
如果您使用的是.NET Framework 4或更高版本,则可以使用线程安全集合.
您可以替换List<T>为ConcurrentBag<T>:
namespace Playground.Sandbox
{
using System.Collections.Concurrent;
using System.Threading.Tasks;
public static class Program
{
public static void Main()
{
var items = new[] { "Foo", "Bar", "Baz" };
var bag = new ConcurrentBag<string>();
Parallel.ForEach(items, bag.Add);
}
}
}
Run Code Online (Sandbox Code Playgroud)
要扩展@ JaradPar的答案,这里是一个完整的实现,具有一些额外的功能,如摘要中所述
/// <summary>
/// a thread-safe list with support for:
/// 1) negative indexes (read from end). "myList[-1]" gets the last value
/// 2) modification while enumerating: enumerates a copy of the collection.
/// </summary>
/// <typeparam name="TValue"></typeparam>
public class ConcurrentList<TValue> : IList<TValue>
{
private object _lock = new object();
private List<TValue> _storage = new List<TValue>();
/// <summary>
/// support for negative indexes (read from end). "myList[-1]" gets the last value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public TValue this[int index]
{
get
{
lock (_lock)
{
if (index < 0)
{
index = this.Count - index;
}
return _storage[index];
}
}
set
{
lock (_lock)
{
if (index < 0)
{
index = this.Count - index;
}
_storage[index] = value;
}
}
}
public void Sort()
{
lock (_lock)
{
_storage.Sort();
}
}
public int Count
{
get
{
return _storage.Count;
}
}
bool ICollection<TValue>.IsReadOnly
{
get
{
return ((IList<TValue>)_storage).IsReadOnly;
}
}
public void Add(TValue item)
{
lock (_lock)
{
_storage.Add(item);
}
}
public void Clear()
{
lock (_lock)
{
_storage.Clear();
}
}
public bool Contains(TValue item)
{
lock (_lock)
{
return _storage.Contains(item);
}
}
public void CopyTo(TValue[] array, int arrayIndex)
{
lock (_lock)
{
_storage.CopyTo(array, arrayIndex);
}
}
public int IndexOf(TValue item)
{
lock (_lock)
{
return _storage.IndexOf(item);
}
}
public void Insert(int index, TValue item)
{
lock (_lock)
{
_storage.Insert(index, item);
}
}
public bool Remove(TValue item)
{
lock (_lock)
{
return _storage.Remove(item);
}
}
public void RemoveAt(int index)
{
lock (_lock)
{
_storage.RemoveAt(index);
}
}
public IEnumerator<TValue> GetEnumerator()
{
lock (_lock)
{
lock (_lock)
{
return (IEnumerator<TValue>)_storage.ToArray().GetEnumerator();
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
46675 次 |
| 最近记录: |