pobieranie wyjątku argumentu w słowniku współbieżnym podczas sortowania i wyświetlania w trakcie aktualizacji

W poniższym programie pojawia się trudny do odtworzenia błąd, w którym pewna liczba wątków aktualizuje równoległy słownik równolegle, a główny wątek wyświetla stan słownika w porządku posortowanym po ustalonych odstępach czasu, aż wszystkie wątki aktualizacji zostaną zakończone.

public void Function(IEnumerable<ICharacterReader> characterReaders, IOutputter outputter)
{
    ConcurrentDictionary<string, int> wordFrequencies = new ConcurrentDictionary<string, int>();
    Thread t = new Thread(() => UpdateWordFrequencies(characterReaders, wordFrequencies));
    bool completed = false;
    var q = from pair in wordFrequencies orderby pair.Value descending, pair.Key select new Tuple<string, int>(pair.Key, pair.Value);
    t.Start();
    Thread.Sleep(0);

    while (!completed)
    {
        completed = t.Join(1);
        outputter.WriteBatch(q);
    }            
}

Funkcja otrzymuje listę strumieni znaków i wyjście. Funkcja utrzymuje równoległy słownik częstotliwości słów słów odczytywanych z każdego ze strumieni znaków (równolegle). Słowa są wczytywane przez nowy wątek, a główny wątek wyprowadza bieżący stan słownika (w porządku posortowanym) co 1 milisekundę, aż wszystkie strumienie wejściowe zostaną odczytane (w praktyce będzie to wynik co około 10 sekund, ale błąd wydaje się pojawiać tylko dla bardzo małych wartości). Funkcja WriteBatch po prostu zapisuje na konsoli:

public void WriteBatch(IEnumerable<Tuple<string, int>> batch)
{
    foreach (var tuple in batch)
    {
        Console.WriteLine("{0} - {1}", tuple.Item1, tuple.Item2);
    }
    Console.WriteLine();
}

Większość wykonań jest w porządku, ale czasami pojawia się następujący błąd w instrukcji foreach w funkcji WriteBatch:

„Nieobsługiwany wyjątek: System.ArgumentException: indeks jest równy lub większy niż długość tablicy, lub liczba elementów w słowniku jest większa niż dostępna przestrzeń od indeksu do końca tablicy docelowej.”

Błąd wydaje się znikać, jeśli główny wątek śpi na chwilę po uruchomieniu wątków aktualizacji i przed uruchomieniem pętli wyświetlania. Wydaje się również, że zniknie, jeśli klauzula orderby zostanie usunięta, a słownik nie zostanie posortowany w zapytaniu linq. Jakieś wyjaśnienia?

Theforeach (var tuple in batch) instrukcja w funkcji WriteBatch podaje błąd. Ślad stosu jest następujący:

Nieobsługiwany wyjątek: System.ArgumentException: Indeks jest równy lub większy niż długość tablicy lub liczba elementów w słowniku jest większa niż dostępna przestrzeń od indeksu do końca tablicy docelowej. at System.Collections.Concurrent.ConcurrentDictionary2.System.Collections.Ge neric.ICollection> .CopyTo (K eyValuePair2 [] tablica, indeks Int32) w System.Linq.Buffer1..ctor (IEnumerable1 source) w System.Linq.OrderedEnumerable1. d__0.MoveNext () at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext () w MyProject.ConsoleOutputter.WriteBatch (wsad IEnumerable1) w C: MyProject ConsoleOutputter.cs: wiersz 10 w MyProject.Function (IEnumerable1 characterReaders, IOutputter outputter)

questionAnswers(2)

yourAnswerToTheQuestion