Uygulamanız doğru. Ne yazık ki .NET Framework yerleşik bir eşzamanlı hashset türü sağlamaz. Ancak, bazı geçici çözümler vardır.
ConcurrentDictionary (önerilir)
Bu ilki sınıfı ConcurrentDictionary<TKey, TValue>
ad alanında kullanmaktır System.Collections.Concurrent
. Bu durumda, değer anlamsızdır, bu yüzden basit byte
(bellekte 1 bayt) kullanabiliriz.
private ConcurrentDictionary<string, byte> _data;
Tür, iş parçacığı açısından güvenli olduğundan ve size bir HashSet<T>
anahtar ve değer farklı nesneler dışında aynı avantajları sağladığı için bu önerilen seçenektir .
Kaynak: Sosyal MSDN
ConcurrentBag
Yinelenen girişleri dikkate almazsanız, sınıfı bir ConcurrentBag<T>
önceki sınıfın aynı ad alanında kullanabilirsiniz .
private ConcurrentBag<string> _data;
Kendinden uygulama
Son olarak, yaptığınız gibi, kilit veya .NET'in iş parçacığı için güvenli olmasını sağladığı diğer yolları kullanarak kendi veri türünüzü uygulayabilirsiniz. İşte harika bir örnek: .Net'te ConcurrentHashSet nasıl uygulanır?
Bu çözümün tek dezavantajı, türün HashSet<T>
okuma işlemleri için bile resmi olarak eşzamanlı erişim olmamasıdır.
Bağlantılı yazının kodunu alıntıladım (aslında Ben Mosher tarafından yazılmıştır ).
using System;
using System.Collections.Generic;
using System.Threading;
namespace BlahBlah.Utilities
{
public class ConcurrentHashSet<T> : IDisposable
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private readonly HashSet<T> _hashSet = new HashSet<T>();
#region Implementation of ICollection<T> ...ish
public bool Add(T item)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Add(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public void Clear()
{
_lock.EnterWriteLock();
try
{
_hashSet.Clear();
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public bool Contains(T item)
{
_lock.EnterReadLock();
try
{
return _hashSet.Contains(item);
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
public bool Remove(T item)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Remove(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public int Count
{
get
{
_lock.EnterReadLock();
try
{
return _hashSet.Count;
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
}
#endregion
#region Dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
if (_lock != null)
_lock.Dispose();
}
~ConcurrentHashSet()
{
Dispose(false);
}
#endregion
}
}
DÜZENLEME:try
Bir istisna atabilir ve finally
bloklarda bulunan talimatları yürütebileceğinden , giriş kilidi yöntemlerini blokların üzerine taşıyın .
System.Collections.Concurrent