private async Task DictionaryConcurrentAccessDetection <TKey, TValue>(PooledDictionary <TKey, TValue> dictionary, bool isValueType, object comparer, Action <PooledDictionary <TKey, TValue> > add, Action <PooledDictionary <TKey, TValue> > get, Action <PooledDictionary <TKey, TValue> > remove, Action <PooledDictionary <TKey, TValue> > removeOutParam) { Task task = Task.Factory.StartNew(() => { // Get the Dictionary into a corrupted state, as if it had been corrupted by concurrent access. // We this deterministically by clearing the _entries array using reflection; // this means that every Entry struct has a 'next' field of zero, which causes the infinite loop // that we want Dictionary to break out of FieldInfo entriesField = dictionary.GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance); Array entriesInstance = (Array)entriesField.GetValue(dictionary); Array entryArray = (Array)Activator.CreateInstance(entriesInstance.GetType(), new object[] { ((ICollection)entriesInstance).Count }); entriesField.SetValue(dictionary, entryArray); Assert.Equal(comparer, dictionary.GetType().GetField("_comparer", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(dictionary)); Assert.Equal(isValueType, dictionary.GetType().GetGenericArguments()[0].IsValueType); var tsn = Assert.Throws <InvalidOperationException>(() => add(dictionary)).TargetSite.Name; Assert.Throws <InvalidOperationException>(() => add(dictionary)); Assert.Throws <InvalidOperationException>(() => get(dictionary)); Assert.Throws <InvalidOperationException>(() => remove(dictionary)); Assert.Throws <InvalidOperationException>(() => removeOutParam(dictionary)); }, TaskCreationOptions.LongRunning); // If Dictionary regresses, we do not want to hang here indefinitely Assert.True((await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(60))) == task) && task.IsCompletedSuccessfully); }