.ToList() wirft sporadisch Fehler

  • VB.NET
  • .NET (FX) 4.0

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    .ToList() wirft sporadisch Fehler

    Hallo zusammen,

    ich bekomme sporadisch immer mal wieder eine System.ArgumentException mit folgender Fehlermeldung: "Das Zielarray ist nicht lang genug, um alle Elemente in der Auflistung zu kopieren. Überprüfen Sie Arrayindex und -länge."

    Das Problem daran ist, dass ich mit der Meldung einfach nichts anfangen kann. Der Fehler als solches ist mir schon klar. Ich kopiere aber kein Array.

    Der Aufruf sieht genau so aus:

    VB.NET-Quellcode

    1. Dim entries As List(Of Entry.Base) = _sessions.Values.ToList()


    Wobei _sessions ein Dictionary vom Typ (long, Entry.Base) ist. Und ich will einfach alle Entry.Base in einer extra Liste haben.

    Mir ist komplett schleierhaft was da schief geht. Vorallem tritt das nicht immer auf, sondern wirklich nur sporadisch. Mal kommt der Fehler tagelang nicht.
    @KillaChris Unterbricht die IDE beim Debuggen das Programm an dieser Stelle?
    Dann klick auf die Variable und drück Shift+F9 und sieh sie Dir an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kleiner Hinweis:
    Die ToList-Extension macht auch nur das:

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Shared Function ToList(Of TSource)(source As IEnumerable(Of TSource)) As List(Of TSource)
    3. '... Check ob source null ist
    4. Return New List(Of TSource)(source)
    5. End Function

    Um sicher zu gehen, dass da bei Dir nicht irgendwas komisches passiert, ersetze mal die Zeile so:

    VB.NET-Quellcode

    1. Dim entries As New List(Of Entry.Base)(_sessions.Values)


    Kannst Du auch bitte den StackTrace posten? Denn ich vermute mal, dass die Exception hier auftritt:

    C#-Quellcode

    1. // Konstruktor der List<T>-Klasse:
    2. public List(IEnumerable<T> collection)
    3. {
    4. if (collection == null)
    5. {
    6. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
    7. }
    8. ICollection<T> collection2 = collection as ICollection<T>;
    9. if (collection2 == null)
    10. {
    11. this._size = 0;
    12. this._items = List<T>._emptyArray;
    13. using (IEnumerator<T> enumerator = collection.GetEnumerator())
    14. {
    15. while (enumerator.MoveNext())
    16. {
    17. this.Add(enumerator.Current);
    18. }
    19. }
    20. return;
    21. }
    22. int count = collection2.Count;
    23. if (count == 0)
    24. {
    25. this._items = List<T>._emptyArray;
    26. return;
    27. }
    28. this._items = new T[count];
    29. collection2.CopyTo(this._items, 0); // <<-------------- Hier die Exception
    30. this._size = count;
    31. }

    Ist das der Fall, vermute ich, dass die Implementierung von CopyTo in _sessions.Values fehlerhaft ist (oder die _sessions.Values.Count gibt einen falschen Wert zurück.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ich hab mir deim Debuggen Values schonmal angeschaut. Der Wert ist gesetzt. Da dort aber knapp 2000 Einträge drin sind, kann ich natürlich nicht sagen ob die Einträge alle in Ordnung sind. Ich muss später mal ausprobieren was passiert wenn ein value auf Nothing gesetzt ist.

    Diese Möglichkeit habe ich auch schon ausprobiert:

    VB.NET-Quellcode

    1. Dim entries As New List(Of Entry.Base)(_sessions.Values)


    Hier der StrackTrace:

    System.ArgumentException
    Das Zielarray ist nicht lang genug, um alle Elemente in der Auflistung zu kopieren. Überprüfen Sie Arrayindex und -länge.
    bei System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
    bei System.Collections.Generic.Dictionary`2.ValueCollection.CopyTo(TValue[] array, Int32 index)
    bei System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)

    Es scheint also tatsächlich so zu sein, wie du vermutest.


    Edit:

    So ich habe mal einen Test geschrieben. Dort füge ich in das Dictionary gütlige Werte ein und ab und zu auch einfach mal Nothing. Und danach kopiere ich die Values in eine extra Liste. Das klappt soweit. Daran kanns also schonmal nicht liegen.

    Mal abgesehen davon kann das in meinem Programm aber gar nicht vorkommen, da der Schlüssel im Dictionary die Id des Objekts ist, welches reingepackt wird. Wenn das Objekt Nothing wäre könnte man die Id davon ja gar nicht auslesen und ich würde schon viel früher einen Fehler bekommen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „KillaChris“ ()

    Der StackTrace sagt wirklich CopyTo. Kannst Du bitte die exakte Deklaration von _sessions posten? Du hast oben erwähnt, dass es ein Dictionary ist.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ok, gut soweit.
    Füg mal den folgenden Code unter Dim entries As New List(Of Entry.Base)(_sessions.Values) ein, lass den Code laufen bis die Exception erneut auftritt, ziehe den gelben Pfeil auf die erste Zeile des Codes, setze einen Haltepunkt auf die letzte Zeile und führe den Code aus.

    VB.NET-Quellcode

    1. Dim Values = DirectCast(_sessions.Values, ICollection(Of String))
    2. Dim Values_Count = Values.Count
    3. Dim Values_dictionary = Values.GetType.GetField("dictionary", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance).GetValue(Values)
    4. Dim Values_dictionary_CountProperty = DirectCast(Values_dictionary.GetType.GetProperty("Count", Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance).GetValue(Values_dictionary, Nothing), Integer)
    5. Dim Values_dictionary_countField = DirectCast(Values_dictionary.GetType.GetField("count", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance).GetValue(Values_dictionary), Integer)
    6. Dim Values_dictionary_freeCountField = DirectCast(Values_dictionary.GetType.GetField("freeCount", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance).GetValue(Values_dictionary), Integer)
    7. Dim bp = 0

    Füge dann alle Variable zur Überwachung hinzu und poste das Ergebnis (man kann aus dem Überwachungsfenster herauskopieren, indem man mit gedrückter Shft- oder Ctrl-Taste die Einträge markiert und dann Ctrl+C drückt).

    Poste bitte auch den Code, der _sessions was zuweist. Eventuell ist das kein standardmäßiges Dictionary, sondern etwas, was davon erbt. Oder vielleicht ein Aufruf an die ToDictionary-Extension. Das wäre noch interessant.


    Edit:
    Ist der Fehler eigentlich reproduzierbar? Also kannst Du vielleicht ein Beispiel posten, das die Exception immer auslöst? Eventuell mit anderen Datentypen (Also Dictionary(Of Long, String) oder so).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    KillaChris schrieb:

    Entry.Base
    Was etwas genauer genau ist das?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ErfinderDesRades könnte recht haben, was das Threading betrifft.
    @KillaChris
    Verwendest Du in Deinem Programm irgend eine Form von Multithreading?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils