Parallel For Each - aggregateException

0

Hej, mam pewien problem, który nie za bardzo wiem jak mam rozwiązać.Prosiłbym o rady i sugestie, problem tyczy się zadania na uczelnie. Mianowicie mój program rzuca wyjątkiem. Komunikat jaki wyświetla i wiadomość jaką przechwyciłem to "length cannot be less than zero. (Parameter 'length')". Chodzi z tego co rozumiem o substring() w jednej z metod. Z moich rozkmin, metoda problematyczna:

private static string checkIsThisStringOkay( string theLongestRepreatedPrefix,  string currentWord, string text)
        {
            string temp = text.Substring(0, text.IndexOf(currentWord)) + text.Substring((text.IndexOf(currentWord) + currentWord.Length));
            if (temp.Contains(currentWord))
            {
                return currentWord;   
            }
            else
            {
                currentWord = currentWord.Substring(0, currentWord.Length - 1);
                checkIsThisStringOkay( theLongestRepreatedPrefix,  currentWord, text);
                return currentWord;
            }
        }

Problem zaczął się gdy chciałęm przyśpieszyć działanie kodu, dodając Parallel.ForEach. Gdy wszystko leciało sekwencyjnie po kolei każda krawędź, to nie było problemu, żadnych wyjątków i wynik dla testowanego przykładu dobry. Tylko teraz to niestety nie działa. Za trochę dziwne i niezrozumiałe dla mnie uważam, iż jeżeli postawię pułapkę w tym Parallel.Foreachu i puszczę program kilka razy, to raz na 10 nie wywala wyjątku tylko działa i przechodzi. Trochę nie rozumiem... Pewnie to chodzi o równoległą pracę i potrzebę zgłębienia przeze mnie równoległego działania forów/ foreachy. Gdyby ktoś mógł podpowiedzieć, co należy zrobić byłbym wdzięczny bardzo.

Parallel.ForEach(trie._root._edges,
                (edge) =>
                {
                    Dictionary<char, Edge<int>> keyValuePairConvertedToDictonary = new Dictionary<char, Edge<int>> { { edge.Key, edge.Value } };
                    string myLongestWord = "";
                    TraversePostOrder(keyValuePairConvertedToDictonary, ref myLongestWord, ref temp, args[0]);
                    myLongestWordEdge.Add(myLongestWord);
                }
                );

Dzięki za poświęcony mi czas =) bardzo doceniam i pozdrawiam Michał/ Jarver :)
PS. link do gita z całym kodem gdyby ktoś chciał zerknać

1
 currentWord = currentWord.Substring(0, currentWord.Length - 1);

Zauważ ,że gdy currentWord będzie puste program będzie próbować się odwołać do indeksu -1 ,którego być nie może.

0

Bardzo słuszna uwaga Botek, ale nie powinno dojść do takiej sytuacji raczej i jest to spowodowane innym miejscem w kodzie, gdzie dochodzi do pierwotnego wywołania tej funkcji. Warunkiem by to się wywołało jest by długość najdłuższego powtarzającego się członu, była mniejsza niż obecnie sprawdzane słowo, zatem długość obecnie sprawdzanego słowa musi być większa niz najdługższego powtórzonego, dla tego ta długość current worda nie powinna przyjmować value 0, tak by po odjęciu 1 wywalało wyjątek.

 public static void TraversePostOrder(IDictionary<char, Edge<int>> edges, ref string theLongestRepreatedPrefix, ref string currentWord, string text)
        {
            if (edges.Count != 0)
            {

                if (theLongestRepreatedPrefix.Length < currentWord.Length)
                {
                    theLongestRepreatedPrefix = checkIsThisStringOkay(  theLongestRepreatedPrefix,  currentWord,  text);
                    

                }
                foreach (var item in edges)
                {
                    currentWord += item.Value.Label;
                    TraversePostOrder(item.Value.Target._edges, ref theLongestRepreatedPrefix, ref currentWord,text);
                    currentWord = currentWord.Substring(0, (currentWord.Length - item.Value.Label.Length));
                }
            }
        }

No mimo wszystko pozwoliłem sobie dopisać fragment, który miał za celu wykluczyć długość currnetWorda na 0. Wyjątek nadal się sypie. Wniosek, to chyba nie pomogło. No chyba że coś źle rozumiem....

if (currentWord.Length>0)
                {
                    currentWord = currentWord.Substring(0, currentWord.Length - 1);
                    checkIsThisStringOkay(theLongestRepreatedPrefix, currentWord, text);
                }

Co by nie było bardzo dziękuję Botek za zainteresowanie i pomoc, radę :)

0

Przekomipilowałem na szybko i z mojego debugger wynika ,że

string temp = text.Substring(0, text.IndexOf(currentWord)) + text.Substring((text.IndexOf(currentWord) + currentWord.Length));

Jeśli słowo nie zawiera się w tym stringu to wyrzuci program bo indexof nie znajdzie wartości czyli ustawi wartość -1.

Możesz to sprawdzić za pomocą Contains lub też po prostu sprawdzić sobie indexof wcześniej i sprawdzić czy jest on równy -1. (polecam drugą opcję)

Ale ogólnie to widzę jedną sprzeczność skoro nazwa jest checkIsThisStringOkay to ja bym oczekiwał boola a ty zwracasz stringa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1