using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadSafeEnumerable
{
public static class Counter
{
public static long Alive = 0;
public static long Dead = 0;
}
public class ThreadsafeEnumerator<T> : IEnumerator<T>
{
private readonly IEnumerator<T> _innerCollection;
private readonly ReaderWriterLockSlim _rwLock;
public ThreadsafeEnumerator(IEnumerator<T> innerCollection, ReaderWriterLockSlim rwLock)
{
_rwLock = rwLock;
_innerCollection = innerCollection;
rwLock.EnterReadLock();
++Counter.Alive;
}
public void Dispose()
{
_rwLock.ExitReadLock();
--Counter.Alive;
++Counter.Dead;
}
public bool MoveNext()
{
return _innerCollection.MoveNext();
}
public void Reset()
{
_innerCollection.Reset();
}
public T Current { get { return _innerCollection.Current; } }
object IEnumerator.Current { get { return Current; } }
}
public class ThreadSafeCollection<T> : IList<T>
{
internal List<T> InnerList;
readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
protected ReaderWriterLockSlim RwLock
{
get
{
return _rwLock;
}
}
#region "Constructors"
protected ThreadSafeCollection()
{
InnerList = new List<T>();
}
protected ThreadSafeCollection(params T[] items)
: this()
{
if (items == null)
{
return;
}
AddRange(items);
}
#endregion
#region "Destructor"
~ThreadSafeCollection()
{
_rwLock.Dispose();
}
#endregion
#region "Public methods"
public void AddRange(IEnumerable<T> items)
{
try
{
_rwLock.EnterWriteLock();
foreach (var item in items.Where(x => x != null))
{
InnerList.Add(item);
}
}
finally
{
_rwLock.ExitWriteLock();
}
}
#endregion
internal void RemoveAll(Predicate<T> predicate)
{
try
{
_rwLock.EnterWriteLock();
InnerList.RemoveAll(predicate);
}
finally
{
_rwLock.ExitWriteLock();
}
}
#region "Interface methods"
public IEnumerator<T> GetEnumerator()
{
_rwLock.EnterReadLock();
try
{
return new ThreadsafeEnumerator<T>(InnerList.GetEnumerator(), _rwLock);
}
finally
{
_rwLock.ExitReadLock();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
try
{
_rwLock.EnterWriteLock();
InnerList.Add(item);
}
finally
{
_rwLock.ExitWriteLock();
}
}
public void Clear()
{
try
{
_rwLock.EnterWriteLock();
InnerList.Clear();
}
finally
{
_rwLock.ExitWriteLock();
}
}
public bool Contains(T item)
{
try
{
_rwLock.EnterReadLock();
return InnerList.Contains(item);
}
finally
{
_rwLock.ExitReadLock();
}
}
public void CopyTo(T[] array, int arrayIndex)
{
_rwLock.EnterReadLock();
InnerList.CopyTo(array, arrayIndex);
_rwLock.ExitReadLock();
}
public bool Remove(T item)
{
try
{
_rwLock.EnterWriteLock();
return InnerList.Remove(item);
}
finally
{
_rwLock.ExitWriteLock();
}
}
public int Count
{
get { return InnerList.Count; }
}
public bool IsReadOnly
{
get { return ((IList<T>)InnerList).IsReadOnly; }
}
public int IndexOf(T item)
{
try
{
_rwLock.EnterReadLock();
return InnerList.IndexOf(item);
}
finally
{
_rwLock.ExitReadLock();
}
}
public void Insert(int index, T item)
{
try
{
_rwLock.EnterWriteLock();
InnerList.Insert(index, item);
}
finally
{
_rwLock.ExitWriteLock();
}
}
public void RemoveAt(int index)
{
try
{
_rwLock.EnterWriteLock();
InnerList.RemoveAt(index);
}
finally
{
_rwLock.ExitWriteLock();
}
}
public T this[int index]
{
get
{
try
{
_rwLock.EnterReadLock();
return InnerList[index];
}
finally
{
_rwLock.ExitReadLock();
}
}
set
{
try
{
_rwLock.EnterWriteLock();
InnerList[index] = value;
}
finally
{
_rwLock.ExitWriteLock();
}
}
}
#endregion
#region "Public override methods"
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return this == (ThreadSafeCollection<T>)obj;
}
public override int GetHashCode()
{
try
{
_rwLock.EnterReadLock();
return InnerList.Aggregate(17, (current, x) => current + current * 23 + x.GetHashCode());
}
finally
{
_rwLock.ExitReadLock();
}
}
public static bool operator ==(ThreadSafeCollection<T> obj1, ThreadSafeCollection<T> obj2)
{
if (ReferenceEquals(obj1, obj2))
{
return true;
}
if (ReferenceEquals(obj1, null) || ReferenceEquals(obj2, null))
{
return false;
}
var match = obj1.InnerList.Count == obj2.InnerList.Count;
if (!match)
{
return false;
}
for (var i = 0; i < obj1.InnerList.Count; i++)
{
match = obj1.InnerList.Any(x => x.Equals(obj2.InnerList[i]));
if (!match)
{
break;
}
}
return match;
}
public static bool operator !=(ThreadSafeCollection<T> obj1, ThreadSafeCollection<T> obj2)
{
return !(obj1 == obj2);
}
#endregion
#region "protected methods"
#endregion
}
public class MyStringCollection : ThreadSafeCollection<string>
{
}
[DataContract]
public class MyData
{
MyStringCollection _strings;
[DataMember]
public MyStringCollection Strings
{
get
{
if (_strings == null)
{
_strings = new MyStringCollection();
}
return _strings;
}
}
}
class Program
{
static void Main(string[] args)
{
MyData o1 = new MyData();
o1.Strings.Add("R1");
o1.Strings.Add("R2");
o1.Strings.Add("R3");
Console.WriteLine($"BEFORE Counter.Alive = {Counter.Alive} ");
using (var ms = new MemoryStream())
{
var dcs = new DataContractSerializer(o1.GetType());
dcs.WriteObject(ms, o1);
var serialisedString = Encoding.UTF8.GetString(ms.ToArray());
}
Console.WriteLine($"AFTER Counter.Alive = {Counter.Alive} ");
try
{
o1.Strings.Add("R4");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Exit.");
}
}
}
我正在使用DataContractSerializer
来序列化集合。此集合由类ThreadSafeCollection
实现为线程安全。 ThreadSafeCollection
实施IList<T>
。函数IEnumerator<T>.GetEnumerator()
在此类中实现。这将返回ThreadSafeEnumerator
类对象。 ThreadSafeEnumerator
也由我实施。
问题:
ThreadsafeEnumerator
中的处理功能未被调用。由于这个_rwLock的读锁(类型ReaderWriterLockSlim)没有被释放。因此,当调用Add时,我无法获得写锁定。请参阅主函数try catch中的代码,它尝试添加但失败。