ConcurrentDictionary Schleifen Problem

  • VB.NET
  • .NET (FX) 4.0

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von chefsache.

    ConcurrentDictionary Schleifen Problem

    Hallo Leute,

    ich habe eine Unsicherheit bei einem ConcurrentDictionary.

    Das Problem:
    Ich speichere und lade Inhalte eines ConcurrentDictionary(Of String,Integer) in eine Textdatei.
    Nun lasse ich eine for each drüber laufen und stelle fest => alles gut, Reihenfolge bleibt erhalten.
    Jetzt mache ich das in einer Multithreadumgebung: IIS Server => bums, ConcurrentDictionary ist "durcheinander".

    Ich löse das Problem durch eine LINQ Sortierung vor dem Speichern und nach dem Laden und direkt vor der for each Schleife.

    Meine Sorge ist, dass die Reihenfolge immer noch nicht garantiert werden könnte. (Ich kann gerade nicht testen, bzw weiss nicht wie.)
    Ist meine Lösung "richtig"/sicher ?!
    ich denke nicht, dass ein ConcurrentDictionary mit Reihenfolgen richtig umgeht. Weil ein Dictionary ist generell nicht daraufhin designed, Elemente in einer Reihenfolge auszugeben (Mag sein, dasses das dennoch tut, aber das ist nicht eigentlich Aufgabe eines Dictionaries).
    Evtl. wäre eine ConcurrentCollection da besser geeignet.

    Allerdings wenn mehrere Threads reinschaufeln kann es ja schon vom Prinzip her keine definierte Reihenfolge mehr geben.
    Es ist so:

    Die Reihenfolge ist beim Erstellen durch eine parallel.for Schleife wahllos/durcheinander, korrekt. Alles gut.

    Jedoch wenn das Objekt "ConcurrentDictionary" erstmal komplett fertig ist, soll diese Reihenfolge für immer gelten.
    Das tut sie, wie beschrieben auch, wenn ein Thread eine neues Objekt "ConcurrentDictionary" aus dem Textfile holt und dann durchläuft.

    Ist der letztere Vorgang(das holen) jedoch in einer Multithreading-Umgebung, verändert sich die geladene Reihenfolge. d.h. in der Textdatei ist die Reihenfolge noch erhalten, aber irgendwo auf dem Weg zum Durchlauf mit for each ist die Reihenfolge dann verändert worden. (stichwort GarbageCollector vermutlich).

    Ich habe gerade mal versucht einen ConcurrentQueue(of T) zu nehmen. Dabei fehlt mir dann aber das TryAdd() um distinct/unique hinzubekommen + die Sortierung gestaltet sich aufwendiger. (muss nach key und value sortieren)

    ErfinderDesRades schrieb:

    chefsache schrieb:

    Das tut sie, wie beschrieben auch, wenn ein Thread eine neues Objekt "ConcurrentDictionary" aus dem Textfile holt und dann durchläuft.
    Das ergibt für mich keinen Sinn.
    Aus einem Textfile kann man kein ConcurrentDictionary holen.


    Hi Erfinder,

    das war abkürzend geschrieben. Natürlich lade ich Zeile für Zeile und mache ein TryAdd(line,0). (string, integer)
    Kann da schon etwas durcheinander gehen? Also meine StandaloneApp macht "while ...readline" in einem Rutsch durch und die IIS Umgebung macht hier vielleicht schon "Pausen" für andere Threads/Clients?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „chefsache“ ()

    ErfinderDesRades schrieb:

    Keine Ahnung, was du meinst.

    Was meinst du mit Durcheinander?
    Ein Dictionary liefert unter einem Schlüssel einen Wert - was kann da durcheinander sein? liefert es unter dem richtigen Schlüssel falsche Werte?


    Beispiel: Ich habe ein Dictionary auf bis es fertig ist.
    Dann muss ich es durchlaufen mit:

    for each keyValuePair in dic
    keyValuePair.TryGet....
    next

    Von dieser Reihenfolge rede ich. In meiner StandaloneApp wird die gewährleistet und beim IIS nicht.
    Ich weiss garnet recht, was der IIS ist - Inwiefern sollte der in deim Dictionary eine Reihenfolge gewährleisten oder durcheinander bringen?

    Und deine Schleife kommt mir sehr merkwürdig vor: keyValuePair.TryGet... - gibts das?

    Also ich reime mir jetzt mal was zusammen, und du sagst, ob das das ist, was du zu sagen versuchst, ja?

    Du hast iwie eine StandardApp, und die befüllt iwie ein ConcurrentDictionary.
    Und iwie befüllt etwas, was "IIS" heisst, ebenfalls ein ConcurrentDictionary.
    Und wenn man nun die beiden Dictionaries mit Foreach durchläuft, dann unterscheiden sich die Reihenfolgen der Elemente.

    War's das?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ja

    de.wikipedia.org/wiki/Microsof…rnet_Information_Services
    WCF Service + WinForms oder asp or whatever VS meine StandAloneApp

    TryAdd gibt es auf dem ConcurrentDictionary

    Wie findest du es, wenn ich "einfach" aus ConcurrentDictionary(Of String, Integer) ein ConcurrentDictionary(Of String, structure) mache? Die Structure hält dann einen index vor und den eigentlichen Value (eine frequenz/häufigkeit). Kann ich dann noch nach Value sortieren?
    ein dictionary ist nicht zum sortieren da, sondern zum nachschlagen, die reihenfolge in einem dictionary ist nie garantiert. wenn du ein concurrent sorted dictionary brauchst musst du es eben selber implementieren, eine schnelle google suche hat da einiges vielversprechendes ergeben.

    chefsache schrieb:

    Wie findest du es, wenn ich "einfach" aus ConcurrentDictionary(Of String, Integer) ein ConcurrentDictionary(Of String, structure) mache?
    Eine structure zu nehmen ist eine gute Idee. Aber nimm lieber - wie bereits gesagt - eine ConcurrentCollection(Of structure).
    Direkt kannste die nicht sortieren, aber du kannst sie auslesen in eine List(Of structure), die kannste dann sortieren.
    Denn du brauchst keine Dictionary-Funktionalität, dann nimm auch kein Dictionary.
    Lade ich mir ein ein ConcurrentSortedDic herunter muss ich es 100% verstehen bevor ich es einsetzen darf. Das kann ich in 1-3 Tagen nicht schaffen.

    Selber eins bauen indem man ein SortedDic nimmt und davon erbt und dann tryadd und synclock Sachen machen ist auch bischen too much...

    Bin mehr so der ratiopharm Typ. Ich erweitere erstmal die vorhandene Dic um ein Object statt Integer. Das sollte klappen. Dann habe ich im Obj einen idx, fertig.

    Andere Vorschläge?

    ps bin halt Anfänger in .net Welt, da kann ich mir nicht mal ebend einen neuen DatenTyp basteln.
    Eine ConcurrentQueue (sorry, ConcurrentCollection gibts nicht - hatte falschen Datentyp genannt) musst du von nirgends runterladen, die ist im FW dabei, wie es das ConcurrentDictionary auch ist.

    Und - ja, verstehen musste schon, was du tust, das ist bei ConcurrentDictionary ja nicht anders.
    Ob "das vorhandene Dic erweitern um ein Object statt Integer" - also was immer du damit meinen magst - ob das einfacher wird?
    Ich habe schon eine Queue getestet. Da hakte es dann aber daran, dass ich "nicht gucken konnte, ob der Key schon drin ist".

    Beispiel:
    dim myQueue as New ConcurrentQueue(Of MyClass)

    MyClass hat 3 Properties: Key,Value,idx (von mir aus alles Strings)

    Wie überprüfe ich dann bevor ich myQueue.Enqueue(myclass) mache, ob schon eine Instanz mit dem selben Key drin ist? also myclass.Key

    Muss ich mir dann meine eigene ConcurrentQueue implementieren und das contains überschreiben? Richtig?

    EDIT: nehme ich eine Queue fehlt mir ja wieder das TryAdd, das brauche ich aber.

    Also nochmal von vorne:
    Meine Anforderungen sind:

    1. Eindeutigkeit der key strings
    2. eine Summe wie oft der Key vorkommt
    3. ein index an welcher position der key steht


    Was nehme ich da und warum?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „chefsache“ ()

    jo, hätte ich den code von grund auf geschrieben ja.
    dann einfach zusammenzählen und dann hat man auch die frequenz.

    Naja danke Jungs, ich find schon ne passende Lösung für morgen. Das Problem ist, dass ich eine AnfDef für Standalone App bekomme und dann heißt es auf einmal: nun soll die Demo aber auf dem IIS mit Multithreading laufen. Und wer bekommt den Meckern wenn es dann nicht mehr funzt?! Mir ist schon klar, dass ich das absichern muss, aber ohne große Berufserfahrung und Wissen über Threads ist das nicht drin.