A volte viene visualizzato l'errore qui sotto quando chiamo ConcurrentDictionary.ToArray. Errore sotto:.NET ConcurrentDictionary.ToArray() ArgumentException
System.ArgumentException: L'indice è uguale o maggiore della lunghezza della matrice, o il numero di elementi nel dizionario è maggiore dello spazio disponibile dall'indice alla fine della matrice di destinazione . a System.Collections.Concurrent.ConcurrentDictionary
2.System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(KeyValuePair
2 [] matrice, indice Int32) a System.Linq.Buffer1..ctor(IEnumerable
1 fonte) a System.Linq.Enumerable.ToArray [TSource] (IEnumerable1 source) at ...Cache.SlidingCache
2.RemoveExcessAsync (Object state) in ... \ SlidingCache.cs: riga 141 in System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, callback ContextCallback, stato dell'oggetto, preserveSyncCtx booleano) in System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() in System.Threading.ThreadPoolWorkQueue.Dispatch()
Ho notato che in scenari multithread si ottengono a volte eccezioni durante l'ordinamento di ConcurrentDictionary. Vedere la domanda di overflow dello stack here. Quindi ho iniziato a utilizzare ConcurrentDictionary.ToArray prima di ordinare invece. Sembra che ci siano ancora problemi durante la creazione della matrice.
Il dizionario concorrente viene utilizzato per una cache che conserva oggetti e svuota gli ultimi oggetti accessibili quando viene raggiunto il numero massimo di elementi impostato per la cache. La cache è accessibile da più thread e l'errore sopra riportato si verifica quando si tenta di rimuovere gli elementi precedenti in modo che i nuovi elementi possano essere aggiunti all'array. Si prega di vedere alcuni frammenti di codice qui sotto:
public class SlidingCache<TKey, TValue> : IDictionary<TKey, TValue>
{
public int MinCount { get; private set; }
public int MaxCount { get; private set; }
private readonly IDictionary<TKey, CacheValue> _cache = new ConcurrentDictionary<TKey, CacheValue>();
public SlidingCache(int minCount=75000, int maxCount=100000)
{
if (minCount <= 2)
throw new ArgumentException("minCount");
if (maxCount <= minCount)
throw new ArgumentException("maxCount");
MinCount = minCount;
MaxCount = maxCount;
}
#region IDictionary<TKey, TValue>
public int Count
{
get { return _cache.Count; }
}
public TValue this[TKey key]
{
get
{
return _cache[key].Value;
}
set
{
_cache[key]=new CacheValue(value);
RemoveExcess();
}
}
...
#endregion
private void RemoveExcess()
{
if (this.Count <= this.MaxCount || Interlocked.Increment(ref _removingExcess) != 1)
return;
ThreadPool.QueueUserWorkItem(RemoveExcessAsync, null);
}
private int _removingExcess;
private void RemoveExcessAsync(object state)
{
var remove = _cache.ToArray().OrderByDescending(i => i.Value.LastRequestTime).Take(MaxCount - MinCount);
foreach (var pair in remove)
{
_cache.Remove(pair.Key);
}
Interlocked.Exchange(ref _removingExcess, 0);
}
qualcuno può spiegare gentilmente il motivo potenziale per l'eccezione di cui sopra e le eventuali soluzioni alternative?
Grazie.
Grazie mille. Questo ha molto senso. – Kess