Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Iteration σε List<Τ> με μεταβλητό μεγεθος!

Îåêßíçóå áðü ôï ìÝëïò Alexpap. Τελευταία δημοσίευση από το μέλος Panagiotis Kefalidis στις 05-11-2013, 12:05. Υπάρχουν 6 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  26-10-2013, 18:52 74547

    Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Καλησπέρα σε όλους,

    Έχω ένα object τύπου List<T>, το οποίο χρησιμοποιείται ως κοινό resource από κάποια threads. Κάνοντας iterate την λίστα, υπάρχει περίπτωση να αλλάξει το πλήθος των στοιχείων από κάποιο από τα threads, με αποτέλεσμα να δημιουργείται πρόβλημα σε ένα for...each loop. Σκέφτηκα να χρησιμοποιήσω την εντολή lock(), για να κλειδώνει το object κάθε φορά που θα ελέγχει τα στοιχεία της. Υπάρχει κάποιος καλύτερος/σωστότερος τρόπος?

     

    ΥΓ: Το thread που κάνει loop στην λίστα τρέχει συνεχώς, οπότε και κάποιο στοιχείο να μην μπει την ώρα του ελέγχου θα μπει μόλις τελειώσει.

     

     Ευχαριστώ εκ των προτέρων 


    Αλέξανδρος Παπαίωάννου

    "If you can't make it good, at least make it look good." Bill Gates
    Δημοσίευση στην κατηγορία: , , ,
  •  27-10-2013, 18:31 74551 σε απάντηση της 74547

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Θα μπορούσες να χρησιμοποιήσεις ConcurrentDictionary που είναι φτιαγμένο για Concurrent access ή απλά να κάνεις copy πριν το Iteration εάν η λίστα δεν είναι μεγάλη ώστε να μην ξοδεύεις πολύ μνήμη. Το να το lockareis θα σου σκοτώσει αρκέτα το performance εάν παραμένει lockarismeno για αρκετή ώρα κάθε φορά.

     Αυτό που με παραξενεύει είναι ότι χρησιμοποιείς List<T> το οποίο το κάνουν access διάφορα threads ενώ το data structure δεν είναι thread-safe έτσι κι αλλοιώς. Ήδη θα έχεις προβλήματα, ανεξάρτητα απο το Iteration. Πως το έλυσες αυτό τώρα; Η΄ δεν το έλυσες καθόλου; Τώρα εάν δεν χρησιμοποιείς .NET 4.0 και νεότερο, τα Concurrent Collection που είπα πριν δεν υπάρχουν, οπότε θα πρέπει να το lockareis αναγκαστικά, αλλά θα πρέπει να φτιάξεις methods τα οποία κάνουν το Add/Remove έτσι κι αλλοιώς γιατί όπως είπα έχεις και τώρα πρόβλημα, απλά δεν έσκασε ακόμα. Διαφορετικά το Performance πάει περίπατο.

    Δες εδώ -> http://msdn.microsoft.com/en-us/library/system.collections.icollection.issynchronized(v=vs.90).aspx υπάρχει η απάντηση για το πως να το lockareis σωστά για iteration κλπ.


    Παναγιώτης Κεφαλίδης

    "Για να επιτύχεις, θα πρέπει το πάθος σου για την επιτυχία να είναι μεγαλύτερο απο τον φόβο σου για την αποτυχία"

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Παρακαλώ διαβάστε τους όρους χρήσης.
  •  03-11-2013, 14:00 74570 σε απάντηση της 74551

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Ο χρόνος που θα χρειαστεί να μείνει lockαρισμενο το object είναι όσο χρειάζεται η εγγραφή ενός record σε ένα table σε μια βάση δεδομένων, για αυτό ρώτησα και αν θεωρείται ως μια "σωστή" λύση. Χρησιμοποιώ .NET 4.0, άλλα το object που προτείνεις είναι Dictionary, και εγώ θέλω την λίστα πιο πολύ σαν μια ουρά, που θα μπαίνουν object μέσα, που περιμένουν προς εξυπηρέτηση-αφαίρεση από την λίστα. 

    Μετά από λίγο ψάξιμο πάνω στο θέμα "thread-safe lists" βρήκα το ConcurrentBag<T> ( http://msdn.microsoft.com/en-us/library/dd381779.aspx ), αλλά δεν έχω άποψη καθώς δεν το έχω ξαναχρησιμοποιήσει.


    Αλέξανδρος Παπαίωάννου

    "If you can't make it good, at least make it look good." Bill Gates
  •  03-11-2013, 20:05 74572 σε απάντηση της 74570

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Καλησπέρα,

    Ο χρόνος που θα πάρει μια εγγραφή στην βάση μπορεί να είναι από δεκάδες milliseconds - αν η βάση είναι άδεια - σε μερικές εκατοντάδες milliseconds  - αν η βάση έχει μερικές χιλιάδες records - και μπορεί να φτάσε τα seconds, αν έχεις related πίνακες και εκατομμύρια εγγραφές. 

    Αν αυτό που θέλεις είναι να φτιάξεις ένα queue, για προσωρινή αποθήκευση των εγγραφών, πριν μπουν στην βάση από ένα ασύγχρονο μηχανισμό, ίσως θα έπρεπε να κοιτάς προς την μεριά του ConcurrentQueue (http://msdn.microsoft.com/en-us/library/dd267265(v=vs.110).aspx). Μπορείς να δεις αν έχει μέσα στοιχεία, και να τα χειριστείς χωρίς να πρέπει να κλειδώσεις το αντικείμενο, έστω και αν πρέπει να κάνεις iteration σε αυτά...

      

    George J. 


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  05-11-2013, 10:06 74582 σε απάντηση της 74572

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Πλησιάζουμε, πλησιάζουμε! Stick out tongue

    Το σενάριο είναι πολύ συνηθισμένο σε multithreaded εφαρμογές και έχει και όνομα: Producer/Consumer. Απλά και μόνο ψάχνοντας με αυτά τα keywords θα βρεις πολλές τεχνικές για να το αντιμετωπίσεις.

    Στο .NET 4 και άνω υπάρχουν πολλοί τρόπο να το αντιμετωπίσεις και κανένας δεν χρειάζεται lock.

    Μία περίπτωση είναι να χρησιμοποιήσεις το BlockingCollection (το οποίο εσωτερικά χρησιμοποιεί το ConcurrentQueue). Το ένα thread γράφει στο collection ενώ το άλλο είτε καλεί την GetConsumingEnumerable() για να διαβάσει, ή καλεί την Take() για να μπλοκάρει μέχρι να γραφτεί κάτι στο collection. Το BlockingCollection εσωτερικά χρησιμοποιεί το ConcurrentQueue αλλά μπορείς να το αντικαταστήσεις με το ConcurrentStack ή οποιοδήποτε άλλο collection υλοποιεί το IProducerConsumerCollection interface και σου δίνει την queueing συμπεριφορά που θέλεις (π.χ. priority queue?)

    Και πριν διαμαρτυρηθεί ο Νίκος ο Παλλαδινός, το κύριο μειονέκτημα του BlockingCollection είναι ότι ... μπλοκάρεις όντως ένα thread που περιμένει μέχρι να του δώσεις δεδομένα.

     Άλλη λύση, είναι να χρησιμοποιήσεις το ActionBlock του TPL DataFlow. Το ActionBlock δέχεται δεδομένα ως input, τα επεξεργάζεται με ένα ή περισσότερα δικά του threads (χωρίς να μπλοκάρει) και γράφει το αποτέλεσμα σε ένα output buffer. Μπορείς να συνδέσεις blocks μεταξύ τους σε ένα Pipeline και π.χ. το ένα να επεξεργάζεται τα inputs και το επόμενο να αποθηκεύει τα αποτελέσματα στη βάση όπως έρχονται.

    Το ωραίο με το DataFlow είναι ότι μπορείς να συνδέσεις πολλά βήματα μεταξύ τους σαν Lego και να έχεις το καθένα να εκτελείται σε ξεχωριστό thread. Αυτό απλουστεύει απίστευτα τον προγραμματισμό του κάθε βήματος καθώς το καθένα είναι απομονωμένο και δεν σε απασχολεί πως θα τα συγχρονίσεις ή πως θα διαχειριστείς τα threads. Μπορείς έτσι να σπάσεις την επεξεργασία σε πολύ περισσότερα κομμάτια απ' ότι με ένα μόνο BlockingCollection


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  05-11-2013, 11:53 74584 σε απάντηση της 74582

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Το μόνο πρόβλημα είναι ότι το TPL DataFlow είναι διαθέσιμο σε 4.5 κι όχι σε 4.0, οπότε θα πρέπει να αρκεστεί σε Task και ContinueWith (χοντρικά) αμα θέλει να κάνει chain από βήματα. Βέβαια το ότι θα χρησιμοποιήσει Task δεν σημαίνει ότι θα τρέξει και σε ξεχωριστά thread, αλλά αυτό είναι άλλο θέμα υποθέτω.
    Παναγιώτης Κεφαλίδης

    "Για να επιτύχεις, θα πρέπει το πάθος σου για την επιτυχία να είναι μεγαλύτερο απο τον φόβο σου για την αποτυχία"

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Παρακαλώ διαβάστε τους όρους χρήσης.
  •  05-11-2013, 12:05 74585 σε απάντηση της 74584

    Απ: Iteration σε List<Τ> με μεταβλητό μεγεθος!

    Το μόνο που δεν ξέρω είναι εάν το TPL Target pack για 4.0 (όπως και το Async) το περνάει.
    Παναγιώτης Κεφαλίδης

    "Για να επιτύχεις, θα πρέπει το πάθος σου για την επιτυχία να είναι μεγαλύτερο απο τον φόβο σου για την αποτυχία"

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Παρακαλώ διαβάστε τους όρους χρήσης.
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems