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

 

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

Ταυτόχρονο update σε 2 UI.

Îåêßíçóå áðü ôï ìÝëïò pontifikas. Τελευταία δημοσίευση από το μέλος George Parissis στις 28-10-2011, 02:21. Υπάρχουν 9 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  23-10-2011, 23:14 67884

    Ταυτόχρονο update σε 2 UI.

    Έχω μια φόρμα που έχει ένα TreeList το οποίο εμπλουτίζω από κάποιο DataSource. 
    Το Datasource έχει αρκετές χιλιάδες εγγραφές (εκατοντάδες χιλιάδες ίσως).
    Ταυτόχρονα με τον εμπλουτισμό του TreeList, θέλω να σηκώσω μια φόρμα που θα περιέχει ένα ProgressBar με σκοπό να δείξω στον χρήστη ότι κάτι
    συμβαίνει, και πόσο θέλει ακόμα για να τελειώσει. 
    Η φόρμα με το Progressbar θέλω να είναι Modal ώστε να μην μπορεί ο χρήστης να κάνει κάτι άλλο όση 
    ώρα διαρκεί η διαδικασία.
    Το να σηκώσω την ProgressBar στο ίδιο Thread με το Tree και να καλώ την DoEvents 100.000 φορές δεν με βολεύει γιατί είναι πολύ αργό. 
    Χαρακτηριστικά η όλη φόρτωση του δέντρου διαρκεί το πολύ 5'' (χωρίς progress bar), και δεν θα ήθελα να χρειαστεί παραπάνω.

    Πώς θα μπορούσα να πραγματοποιήσω αυτό το σενάριο?

    Ευχαριστώ.
  •  24-10-2011, 00:29 67885 σε απάντηση της 67884

    Απ: Ταυτόχρονο update σε 2 UI.

    Θα σου πρότεινα να χρησιμοποιήσεις το BackgroundWorker control.

    Θα βρεις αρκετά παραδείγματα στο Internet.

    Να ξέρεις όμως γενικά ότι το παραπάνω thread δεν θα σου δώσει την ίδια ταχύτητα απλά δεν θα μπλοκάρει το UI, τίποτα άλλο, αντίθετα θα προσθέσει χρόνο. Οπότε θα κάνεις πάνω από 5".

  •  24-10-2011, 12:00 67888 σε απάντηση της 67884

    Απ: Ταυτόχρονο update σε 2 UI.

    Δούλεψε με BackgroundWorker και μετά έλα στο ITProDevConnections. Έχουμε τρία sessions (ένα του Παναγιώτη Καναβού, ένα δικό μου και ένα του Άγγελου Μπιμπούδη) σχετικά με parallel και async, οπότε θα σου έρθουν ιδέες!

     


    Vir prudens non contra ventum mingit
  •  24-10-2011, 19:21 67894 σε απάντηση της 67888

    Απ: Ταυτόχρονο update σε 2 UI.

    Δεν χρειάζεται να έρθει, του το λέω και τώρα. Βήμα 1ο, ΜΗΝ ΦΟΡΤΩΝΕΙΣ ΠΕΡΙΤΤΑ ΔΕΔΟΜΕΝΑ. Δεν υπάρχει κανένας χρήστης ο οποίος να θέλει να δει ταυτόχρονα σε δέντρο μερικές εκατοντάδες ή χιλιάδες αντικείμενα. Κανένας. Ακόμα και αυτοί που έχουν οθόνες σε μέγεθος IMAX. 

    Αυτό που θέλουν είναι να ανοίξουν ένα κόμβο και να δουν από κάτω τα παιδιά του. Αυτό ΔΕΝ απαιτεί να φορτωθούν όλα τα δεδομένα από την αρχή. 

    Ο σωστός τρόπος είναι είτε να εκμεταλλευτείς τις δυνατότητες virtual loading που έχουν τα περισσότερα control ακριβώς για να φορτώνουν μόνο όσα δεδομένα χρειάζονται κάθε φορά. Ακόμα και αν δεν υπάρχει τέτοια υποστήριξη, π.χ. στο System.Windows.Forms.TreeView, μπορείς να πιάσεις το BeforeExpand event και να φορτώσεις εκεί τους επιπλέον κόμβους που χρειάζεσαι.

    Εξάλλου, το TreeView από μόνο του δεν υποστηρίζει data binding. Το ότι φορτώνεις τους κόμβους με τη μία από ένα μεγάλο dataset είναι καθαρά δική σου επιλογή. Μην το κάνεις έτσι λοιπόν. Ή βρες ένα third party control το οποίο να υποστηρίζει virtual data ή φόρτωσε μόνο ότι χρειάζεσαι.

    Η χρήστη οποιασδήποτε μορφής threading δεν πρόκειται να σε βοηθήσει σε ένα πρόβλημα που έχει να κάνει καθαρά με τον τρόπο που φορτώνεις τα δεδομένα.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  24-10-2011, 22:44 67903 σε απάντηση της 67894

    Απ: Ταυτόχρονο update σε 2 UI.

    Δεν έχει νόημα να κάνω αυτό που λες Παναγιώτη στην δική μου εφαρμογή. Δυστυχώς στην εφαρμογή μου ο χρήστης θέλει να τα δει όλα. 
    Οι κόμβοι στους οποίους αναφέρομαι ΠΡΕΠΕΙ να είναι στο ίδιο επίπεδο. Οπότε αργά η γρήγορα θα πρέπει να ... περιμένω.
    Για δέντρο έχω το TreeList της DevExpress και κάνω Dynamic loading, αλλά για τα παιδιά των κόμβων αυτών. Αυτούς καθ' αυτούς, με τον τρέχων σχεδιασμό, δεν τους γλιτώνω....

    Όσον αφορά τον BackgroundWorker, δεν νομίζω ότι είναι σωστό.  Ο Background εκτελεί μια "χρονοβόρα διαδικασία" (εμπλουτισμός δέντρου) σε ξεχωριστό thread. 
    Η διαδικασία αυτή όμως τυγχάνει να κάνει upadte το UI καθώς εξελίσσεται. Αυτό παραβιάζει την αρχή "Thou shalt not operate on a window from other than its creating thread."
    Για αυτό τόνισα τον τίτλο ότι έχω updates σε 2 UI.
    Ή κάνω λάθος???

    Όσο για το να παραστώ στο event.... μακάρι αλλά επειδή "Λεφτά υπάρχουν", βρεθήκαμε στην ξενιτιά...

  •  24-10-2011, 23:00 67904 σε απάντηση της 67903

    Απ: Ταυτόχρονο update σε 2 UI.

    Νόημα δεν έχει να δείξεις εκατοντάδες κόμβους στο ίδιο επίπεδο. Τί προσπαθείς να δείξεις και πως είναι δυνατόν ο χρήστης να χρησιμοποιήσει αυτό το πράγμα? Ακόμα κι έτσι, δεν θα έπρεπε να βλέπεις καθυστέρηση, εκτός και αν προσπαθείς να φορτώσεις όλο το δέντρο με τη μία αντί για το πρώτο επίπεδο μόνο.

    Το μόνο σίγουρο είναι ότι οι χρήστες σου δεν ζήτησαν να βλέπουν εκατοντάδες κόμβους στο ίδιο επίπεδο, ακόμα και αν το είπαν ή το έγραψαν έτσι. Πρέπει να σκεφτείς τί θέλουν να κάνουν και να σχεδιάσεις ένα UI που τους επιτρέπει να το κάνουν. Διαφορετικά δεν πρόκειται να σταματήσουν να γκρινιάζουν ότι το ένα δεν δουλεύει και το άλλο αργεί.

    Μάλλον αντί για TreeList ψάχνεις για ListTree ή μάλλον ένα List για το πρώτο επίπεδο και ένα TreeList από εκεί και κάτω. Δεν είπε κανείς ότι πρέπει ντε και καλά να χρησιμοποιήσεις το ίδιο control για τα πάντα. Εξάλλου και το TreeList είναι συνδυασμός ενός Treeview με ένα Grid.

    Όσο για το Backgroundworker, είναι αυτό που λέει το Κολλητήρι "το πήραμε μόδα κι έγινε συνήθειο". Στην πραγματικότητα δεν σου δίνει κάτι παραπάνω από ένα Task στο .NET 4. Στην περίπτωση έχει κάποιο νόημα επειδή σηκώνει το Progress event το οποίο μπορείς να χρησιμοποιήσεις για να δείξεις ένα progress bar. Για να κάνεις όμως update κάποιο άλλο control θα πρέπει να χρησιμοποιήσεις το κατάλληλο Invoke για να γίνει το update από το ένα thread στο άλλο.



    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  24-10-2011, 23:28 67905 σε απάντηση της 67904

    Απ: Ταυτόχρονο update σε 2 UI.

    Τώρα που το λες θα μπορούσα να έκανα ένα αλφαβητικό Groupping στα ονόματα, και να έχω 26 nodes σε πρώτο επίπεδο.
    αλλά ο χρήστης θέλει να κάνει και Incremenal search και δεν ξέρω αν θα πάει μακρυά η βαλίτσα... 
    Σε κάθε περίπτωση θα πρέπει να συνεννοηθώ με τον Manager μου.

    Θα προσπαθήσω να ξεχωρίσω τους συμμετέχοντες και να καλέσω τις κατάλληλες Invoke από τα κατάλληλα objects και αν το καταφέρω θα αναρτήσω κώδικα.

  •  25-10-2011, 02:30 67908 σε απάντηση της 67903

    Απ: Ταυτόχρονο update σε 2 UI.

    Θα σου απαντήσω για το BackgroundWorker.

    Πρώτα έχω μία απορία. Με ποιο τρόπο διαβάζεις τα δεδομένα από την βάση. Χρησιμοποιείς Dataset, POCO classes που φορτώνεις με DataReader ή κάποιον άλλο τρόπο π.χ Entity Framework, XPO, κ.τ.λ

    Ο BackgroundWorker είναι ένα σχετικά εύκολο control. Όταν καλείς την DoWork εκτελεί σε άλλο Thread τον κώδικα που θα του βάλεις μέσα εκεί. Στην περίπτωσή σου θα ήταν ο κώδικας σύνδεσης στην βάση και ανάγνωσης εγγραφών. Μέσα από εκεί μπορείς να καλέσεις την ReportProgress η οποία κάνει raise ένα event στο Main Thread της εφαρμογής. Στον κώδικα διαχείρισης του event μπορείς να ενημερώσεις ότι θέλεις στο UI. Όταν τελειώσει η εργασία του BackgroundWorker τότε καλείτε ένα ακόμα event που αν δεν κάνω λάθος είναι το Work Completed το οποίο επίσης γίνεται raise στο main thread της εφαρμογής. Εκεί για παράδειγμα θα μπορούσες να περάσεις την λίστα με της εγγραφές που γέμισες από πριν στο άλλο thread να κλείσεις την φόρμα με το ProgressBar και να κάνει Bind την λίστα εκεί που θέλεις.

    Και δεν παραβιάζεται η αρχή που έχεις γράψει. Από την άλλη μπορείς να χρησιμοποιήσεις και TPL απλά ήθελα να σου ξεκαθαρίσω στο μυαλό τι γίνεται με το BackgroundWorker.

     

  •  27-10-2011, 23:30 67947 σε απάντηση της 67884

    Απ: Ταυτόχρονο update σε 2 UI.

    Σίγουρα μπορείς να δείξεις την φόρμα σε άλλο thread αλλά ακόμα και modal να την δείξεις, δεν θα είναι Modal στο κύριο thread. Είχα αντιμετωπίσει παρόμοιο σενάριο το οποίο απαιτούσε την δημιουργία μίας τέτοιας φόρμας με cancel button. Ο τρόπος που είχα επιλέξει τελικά ήταν στην ουσία η υλοποίηση μίας φόρμας τύπου splash screen η οποία έτρεχε σε δικό της process, κάνωντας disable κάποια controls της κύριας φόρμας.

    Παρ όλα αυτά η "ιδέα" δεν άντεξε πολύ αφού το "μαρκούτσι" στην μέση της οθόνης δεν άρεσε (εγώ έφταιγα γιατί ήταν άσχημη η φόρμα..) και προτίμησαν την προσθήκη ενός statusstrip control στο κάτω μέρος της φόρμας με ένα progress bar. To Progress bar έπαιρνε τιμές σε τακτά διαστήματα (ανά εγγραφές ή ανά χρόνο) χωρίς να επηρεάζει υπερβολικά τον χρόνο εμφάνισης των δεδομένων.

  •  28-10-2011, 02:21 67952 σε απάντηση της 67947

    Απ: Ταυτόχρονο update σε 2 UI.

    Συμφωνώ με το σκεπτικό σου αλλά δεν θα την άνοιγα στο δευτερεύων Thread αλλά στο κύριο.

    Θα καλούσα πρώτα την RunWorkerAsync και αμέσως μετά θα εμφάνιζα την φόρμα modal. Έτσι η φόρμα θα άνοιγε στο κύριο thread και θα είχε και το ανάλογο skinning αν είχαμε επιλέξει η εφαρμογή να έχει. (π.χ DevExpress Skinns).

    Άλλωστε στο post μου ανέφερα ότι θα έκλεινε την φόρμα στο Work Completed event το οποίο γίνεται raise στο κυρίως thread. Καλή η παρατήρηση πάντως γιατί όντως είναι ένα θέμα άμα έχεις skin στην εφαρμογή σου. Σου χαλάει όλο το feeling.

Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems