Implementasi Anda benar. Sayangnya, NET Framework. Tidak menyediakan tipe hashset bersamaan built-in. Namun, ada beberapa solusi.
ConcurrentDictionary (disarankan)
Yang pertama ini menggunakan kelas ConcurrentDictionary<TKey, TValue>
di namespace System.Collections.Concurrent
. Dalam kasus ini, nilainya tidak ada gunanya, jadi kita bisa menggunakan yang sederhana byte
(1 byte dalam memori).
private ConcurrentDictionary<string, byte> _data;
Ini adalah opsi yang disarankan karena jenisnya aman untuk thread dan memberi Anda keuntungan yang sama daripada HashSet<T>
kunci kecuali dan nilai adalah objek yang berbeda.
Sumber: MSDN sosial
ConcurrentBag
Jika Anda tidak keberatan dengan entri duplikat, Anda bisa menggunakan kelas ConcurrentBag<T>
di namespace yang sama dengan kelas sebelumnya.
private ConcurrentBag<string> _data;
Implementasi diri
Akhirnya, seperti yang Anda lakukan, Anda bisa mengimplementasikan tipe data Anda sendiri, menggunakan kunci atau cara lain yang disediakan oleh .NET agar Anda aman dari thread. Berikut adalah contoh yang bagus: Bagaimana mengimplementasikan ConcurrentHashSet di .Net
Satu-satunya kelemahan dari solusi ini adalah bahwa jenisnya HashSet<T>
tidak secara bersamaan mengakses, bahkan untuk operasi membaca.
Saya mengutip kode dari posting terkait (aslinya ditulis oleh Ben Mosher ).
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
}
}
EDIT: Pindahkan metode kunci pintu masuk try
blok, karena mereka bisa melempar pengecualian dan menjalankan instruksi yang terkandung dalam finally
blok.
System.Collections.Concurrent