आपका कार्यान्वयन सही है। .NET फ्रेमवर्क दुर्भाग्य से, अंतर्निहित समवर्ती प्रकार प्रदान नहीं करता है। हालाँकि, कुछ वर्कअराउंड हैं।
समवर्ती (अनुशंसित)
यह पहला ConcurrentDictionary<TKey, TValue>
नाम नेमस्पेस में क्लास का उपयोग करने के लिए है System.Collections.Concurrent
। मामले में, मान व्यर्थ है, इसलिए हम एक साधारण byte
(1 बाइट मेमोरी में) का उपयोग कर सकते हैं ।
private ConcurrentDictionary<string, byte> _data;
यह अनुशंसित विकल्प है क्योंकि प्रकार थ्रेड-सुरक्षित है और आपको एक HashSet<T>
कुंजी के अलावा एक ही लाभ प्रदान करता है और मूल्य अलग-अलग ऑब्जेक्ट हैं।
स्रोत: सामाजिक MSDN
ConcurrentBag
यदि आपको डुप्लिकेट प्रविष्टियों के बारे में कोई आपत्ति नहीं है, तो आप ConcurrentBag<T>
पिछली कक्षा के समान नामस्थान में कक्षा का उपयोग कर सकते हैं ।
private ConcurrentBag<string> _data;
स्व कार्यान्वयन
अंत में, जैसा कि आपने किया था, आप अपने स्वयं के डेटा प्रकार को लागू कर सकते हैं, लॉक या अन्य तरीकों से जो .NET आपको थ्रेड-सुरक्षित होने के लिए प्रदान करता है। यहाँ एक महान उदाहरण है: .Net में समवर्ती हाशसेट को कैसे लागू किया जाए
इस समाधान का एकमात्र दोष यह है कि HashSet<T>
पढ़ने के संचालन के लिए भी प्रकार आधिकारिक तौर पर समवर्ती पहुंच नहीं है।
मैं लिंक किए गए पोस्ट का कोड उद्धृत करता हूं (मूल रूप से बेन मोशेर द्वारा लिखित )।
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
}
}
संपादित करें: प्रवेश लॉक विधियों को try
ब्लॉक से अलग करें, क्योंकि वे एक अपवाद फेंक सकते हैं और finally
ब्लॉक में निहित निर्देशों को निष्पादित कर सकते हैं।
System.Collections.Concurrent