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

 

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

Singleton Form

Îåêßíçóå áðü ôï ìÝëïò infoCENTER. Τελευταία δημοσίευση από το μέλος ToyMaker στις 24-02-2006, 12:58. Υπάρχουν 24 απαντήσεις.
Σελίδα 2 από 2 (25 εγγραφές)   < 1 2
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  14-02-2006, 14:47 9668 σε απάντηση της 9656

    Απ: Singleton Form

    Προς axaros. Αυτό που προτείνεις δεν συμβαδίζει με την φιλοφοφία των MDI εφαρμογών. Οπότε δεν θα το σχολιάσω παρακάτω.

    Προς Aris. Συμφωνώ σε αυτό που λες σε γενικές όμως γραμμές. Η Shared μεταβλητή δείχνει σε ένα instance μιας κλάσσης. Οπότε αν αυτό το instance καταργηθεί τότε η shared μεταβλητή δείχνει στο πουθενά. Σχετικά με την dispose που δημιουργήθηκε το θέμα. Είμαι σε μία φάση διαβάσματος για να καταλάβω ακριβώς τι γίνεται για αυτό και δεν έχω απαντήση ακόμα. Η γνώμη μου μέχρι τώρα (και προφανώς εσφαλμένη) ήταν ότι με την dispose είναι σαν να λες στην εφαρμογή καθάρισα με αυτό το Instance και δεν θέλω να το χρησιμοποιήσω άλλο. Οπότε για την εφαρμογή το συγκεκριμένο Instance έχει τελειώσει άσχετα αν δεν έχει καθαρίσει απο την μνήμη. Άλλωστε για κάντε dispose ένα instance κλάσσης και προσπαθήστε μετά να το χρησιμοποιείσεται. Θα πάρετε error. Οπότε σκέφθηκα (και προφανώς εσφαλμένα) ότι το .ΝΕΤ θα έβαζε σε όλους τους pointers που αναφέρονται σε αυτό το Instance την τιμή Nothing (αν μπορεί να θεωρηθεί τιμή) Να μην αφήνει δηλαδή ξεχασμένες μεταβλητές στον κώδικά μου που να αναφέρονται σε άκυρα πράγματα.

    Εγώ πάντος θα περίμενα μία τέτοια συμπεριφορά από ένα managed περιβάλλον. Τελικά από ότι φαίνεται δεν το έπιασα σωστά μου φαίνεται όμως περίεργο αυτό είναι όλο...
  •  14-02-2006, 23:19 9680 σε απάντηση της 9668

    Απ: Singleton Form

    Η μεταβλητή αυτή δεν ζει στον χώρο στο heap που ζουν οι instance-level μεταβλητές. Ζει εκεί που είναι το class definition (απλοποιημένα). Η Dispose θα "καθαρίσει" (θα μαρκάρει σαν ελεύθερο) τον χώρο στο heap. Δεν μπορεί όμως να καθαρίσει το class definition.

    Αυτό που θα μπορούσες να υποθέσεις είναι ότι το περιβάλλον θα μηδένιζε τον pointer (περισσότερο με handle = pointer to pointer μοιάζει). Αλλά, αυτό θα κόστιζε σε χρόνο. Οπότε, εάν έχεις ανάγκη μηδενισμού, το κάνεις μόνος σου. Smile [:)]

    Άρης


    Aris
  •  15-02-2006, 14:44 9724 σε απάντηση της 9680

    Απ: Singleton Form

    Aris δεν θα συμφωνήσω μαζί σου. Ο JIT Compiler κάνει αρκετά άλλα πράγματα που κοστίζουν σε χρόνο. Άλλα αρκετά σημαντικά και άλλα όχι.

    Όπως και να έχει παιδιά σας ευχαριστώ για τον χρόνο σας και για την αναταπόκρισή σας.
  •  16-02-2006, 01:04 9763 σε απάντηση της 9724

    Απ: Singleton Form

    Εδώ έχουν μπλέξει αρκετά τα πράγματα για το τί είναι και τί κάνει η Dispose, τί είναι η shared μεταβλητή και ποιός καταστρέφει ποιόν και πότε.

    1. Η μέθοδος Dispose δεν έχει ΚΑΜΜΙΑ ΕΙΔΙΚΗ ΣΗΜΑΣΙΑ! Θα μπορούσε άνετα να λέγετε Tsalampardoprakopoulopitomethodos και θα δούλευε το ίδιο καλά. Είναι το όνομα που δίνουμε κατά σύμβαση σε μια μέθοδο η οποία περιέχει τον κώδικα που θέλουμε να τρέξει όταν καταστρέφεται ένα αντικείμενο. Για να κληθεί, θα πρέπει να γράψουμε εμείς κώδικα. Το runtime καλεί ΜΟΝΟ την Finalize αυτόματα. ΔΕΝ ΕΧΕΙ ΔΙΑΦΟΡΑ αν καλούμε την Init ή την Dispose ή την Close ή οποιαδήποτε άλλη μέθοδο. Για το runtime είναι όλα το ίδιο.
    Οι κλάσεις που γράφουμε δεν έχουν ορισμένη καμμία μέθοδο Dispose. Είναι μια μέθοδος που γράφει ο συγγραφέας της κλάσης. Αν κληθεί η Dispose, δεν καταστρέφεται κανένα instance και μπορεί να χρησιμοποιηθεί άνετα μετά.

    2. Την Finalize δεν μπορούμε να την καλέσουμε για να προκαλέσουμε την καταστροφή ενός αντικειμένου. Καλείται μόνο από το ίδιο το runtime όταν εκτελείται η διαδικασία καταστροφής ενός instance. Συνεπώς, δεν γίνεται να καταστρέψουμε ένα αντικείμενο με το χέρι και κατά συνέπεια δεν πρόκειται ποτέ να υπάρχουν references σε κατεστραμμένα αντικείμενα.

    3. Ο ΜΟΝΟΣ ΤΡΟΠΟΣ να καταστρέψεις ένα αντικείμενο είναι να καθαρίσεις όλα τα reference σε αυτό. Έτσι, μια shared μεταβλητή που δείχνει στο instance ενός αντικειμένου το κρατάει στη ζωή μέχρι να καθαριστεί και αυτή. ΔΕΝ ΓΙΝΕΤΑΙ να δείχνει μια shared μεταβλητή σε ήδη κατεστραμμένο αντικείμενο.

    4. Το initialization των shared variables γίνεται όταν δημιουργείται το πρώτο instance ενός class ή όταν καλείται για πρώτη φορά μια shared μέθοδος. Τα περιεχόμενα των shared variables δεν καθαρίζονται αυτόματα παρά μόνο όταν κλείνει η εφαρμογή που τα δημιούργησε, καθώς δεν υπάρχει τρόπος να "καταστρέψεις" μία κλάση, μόνο τα instance της.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  16-02-2006, 10:59 9776 σε απάντηση της 9763

    Απ: Singleton Form

    Ο ΠΚ το έθεσε πολύ σωστά. Θα πρότεινα το http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnguinet/html/drguinet4_update.asp (MSDN Lib VS2003) για μιά αναλυτική περιγραφή.

    Το σημαντικό είναι το #4

    Αρης


    Aris
  •  16-02-2006, 17:33 9791 σε απάντηση της 9776

    Απ: Singleton Form

    Όπως έγραψα στις 14/2 αυτή την στιγμή διαβάζω με σκοπό να αποσαφηνίσω το συγκεκριμένο θέμα που έχει προκύψει πρωτίστος για μένα και για όσους ενδιαφέρονται να μπαίνουν σε τόση λεπτομέρεια...

    Επίσης είναι ευπρόσδεκτες όλες οι γνώμες και προτάσεις σας αλλά όλα αυτά δεν χρειάζεται να τα γράψω φυσικά....

    PKanavos. Συμφωνώ σε αυτό που λες σχετικά με την ονομασία της Dispose, θα μπορούσε να λέγεται όπως είπες, άλλωστε αυτό δεν έχει σημασία από την στιγμή που κάνει Implement το IDisposable.

    Επίσης ανέφερες ότι είναι κατά σύμβαση μία ονομασία που δίνουμε σε μία ρουτίνα όταν θέλουμε να καταστρέψουμε ένα αντικείμενο. Αντικείμενο ενοοείς instance; Μεταβλητή; Τι άλλο; Και λέγοντας να καταστρέψει σε τι βαθμό;

    Επίσης έγραψες πως αν κληθεί η Dispose δεν καταστρέφεται κανένα instance και μπορεί να χησιμοποιηθεί άνετα μετά. Χμ... τότε γιατί ο JIT Compiler βάζει μήνυμα λάθους "Cannot access a disposed object."; Άλλωστε αυτό είναι ένα εύκολο παράδειγμα που μπορεί να δοκιμάσει ο καθένας για να δει το συγκεκριμένο μήνυμα.

    Ένα άλλο σοβαρότερο ακόμα θέμα. Η Dispose μπορεί να ακυρώσει να εκτελεστεί η Finalize με την εντολή System.GC.SuppressFinalize. Έχοντας λοιπόν υπ'όψιν το σημείο αυτό και γνωρίζοντας την χρησιμότητα τις Finalize, καταλαβαίνουμε πως τελικά η Dispose μπορεί να κάνει κάτι παραπάνω από ένα cleanup μιας class, από την μεριά της εφαρμογής και όχι από την παρουσία στη μνήμη του συστήματος. Θυμηθήτε το μήνυμα του Compiler και την δυνατότητα να καλεί την παραπάνω εντολή που έγραψα.

    Έπειδή η συζήτηση έχει ανάψει για τα καλά θέλω σε αυτό το σημείο για άλλη μία φορά να σας αναφέρω τον αρχικό μου προβληματισμό για να μην οδηγηθεί η συζήτηση σε άλλα συμπεράσματα και χάσουμε το αρχικό ερώτημα, προβληματισμό.

    Προσωπικά σε ένα managed περιβάλλον θα περίμενα η μεταβλητή ή μεταβλητές που δείχνουν πάνω σε ένα instance classes όταν αυτό το instance δεν μπορεί να χρησιμοποιηθεί άλλο από την εφαρμογή να δείχνουν σε nothing και όχι σε ένα instance που δεν μπορεί να χρησιμοποηθεί άλλο απο την εφαρμογή.

    Η πρόταση κλειδί είναι που δεν μπορεί το συγκεκριμένο instance να χρησιμοποιηθεί άλλο από την εφαρμογή. Θυμηθήτε το μήνυμα του compiler.

    Για να απαντηθεί αυτή η ερώτηση θα πρέπει να γνωρίζουμε τι κάνει η Dispose τι κάνει ο GC πότε και σε ποια φάση καταστρέφεται το instance classes ή δεν είναι διαθέσιμο για την εφαρμογή και μετά θα σταματήσουμε εκεί. Θα ήθελα να ακούσω όμως και την προσωπική σας γνώμη πάνω στον προβληματισμό μου με επιχειρήματα όμως. Και πιστεύω αυτό κάνετε...

    Κάποια από αυτά που γράφω Aris θα τα βρεις και μέσα στο link που μου έστειλες.

    Ευχαριστώ και πάλι όλους για τις απαντήσεις τους και τον χρόνο που διαθέσανε, γνωρίζοντας πόσο πολύτιμος είναι.
  •  16-02-2006, 18:21 9795 σε απάντηση της 9791

    Απ: Singleton Form

    Να αποσαφηνίσουμε και κάτι ακόμα... Ο JIT Compiler δεν έχει καμία σχέση με την όλη ιστορία. Δουλειά του είναι να μετατρέπει τον MSIL κώδικα σε machine κώδικα και αυτό συμβαίνει την πρώτη φορά που τρέχει ένα assembly καθώς και σε κάποιες άλλες ειδικές περιπτώσεις. Ό,τι κουβεντιάζουμε εδώ (Garbage Collection, κλπ), είναι καθαρά functionality του CLR. Έτσι λοιπόν, το "Cannot access a disposed object." δεν είναι μήνυμα που βγάζει ο JIT Compiler. Όταν εμφανιστεί αυτό το μήνυμα, έχει ήδη τρέξει και έχει τελειώσει ο JIT Compiler.

    Τέλος κάτι άλλο: Μην συγχέεις γενικά τη συμπεριφορά όλων των objects στο θέμα του dispose με το πως συμπεριφέρονται οι φόρμες. Οι φόρμες είναι μεν objects που προέρχονται από κλάσεις αλλά έχουν implemented λογική στο Dispose function. Αυτή η λογική βρίσκεται στη base κλάση System.Windows.Forms.Form, οπότε βρίσκεται σε όλες τις φόρμες που κατασκευάζεις.

    Η λογική της Dispose των φορμών είναι ότι άπαξ και γίνουν dispose δεν πρέπει να ξαναχρησιμοποιηθούν, δηλαδή από τη στιγμή που έχουν καθαριστεί τα unmanaged resources δεν έχει νόημα να ξαναχρησιμοποιηθούν παρά μόνο αν φτιαχτεί νέο instance τους. Αν για παράδειγμα, έχεις ανοίξει ένα log file και γράφεις μέσα πράγματα και το κλείσεις με τη Dispose, θα πρέπει να φτιάξεις νέο instance για να ξαναδημιουργηθεί αυτό το log file.
    Έτσι λοιπόν, μιας και δεν μπορεί η φόρμα εκ των πραγμάτων να φύγει από τη μνήμη (μιας και αυτό θα το κάνει ο GC) κρατάει το αν έχει γίνει Dispose εσωτερικά σε ένα boolean member που λέγεται Disposed και εμφανίζει exception αν πας να τις χρησιμοποιήσεις "παράνομα".

    Άρα λοιπόν, αν θέλεις να ελέγξεις αν μπορείς να χρησιμοποιήσεις μια φόρμα, θα πρέπει να πεις

     If someForm Is Nothing OrElse someForm.IsDisposed Then...

    Αρχικά δηλαδή ελέγχεις αν υπάρχει το instance και κατόπιν αν δεν είναι Disposed. To IsDisposed πάλι είναι ένα property που δεν το βρίσκεις πάντοτε σε όλες τις κλάσεις παρά μόνο αν το έχει φτιάξει ο κατασκευαστής τους.

    Για να κλείσουμε, όταν ανοίγεις μια φόρμα με τη μέθοδο Show, και κατόπιν την κλείνεις με τη Close ή πατώντας το "X" τότε η φόρμα γίνεται αυτόματα Disposed ενώ όταν την ανοίγεις με ShowDialog όχι και γι αυτό στη δεύτερη περίπτωση είναι δική σου ευθύνη να καλέσεις τη Dispose.

    Άρα λοιπόν, το θέμα δεν είναι τι περιμένεις εσύ (από φιλοσοφικής άποψης) ότι πρέπει ή δεν πρέπει να γίνεται στο managed περιβάλλον, αλλά το τι συμβαίνει στη πραγματικότητα από αυτούς που έχουν φτιάξει τη κλάση System.Windows.Forms.Form


    Vir prudens non contra ventum mingit
  •  16-02-2006, 20:09 9799 σε απάντηση της 9791

    Απ: Singleton Form

    Εδώ έχει γίνει μία συνηθισμένη παρανόηση. Ο infocenter έχει κάνει μια εσφαλμένη αρχική υπόθεση βασισμένη σε κάποια συμπεριφορά που παρατήρησε και προσπαθεί να προσαρμόσει όσα διαβάζει και όσα παρατηρεί σε αυτή. Το αποτέλεσμα είναι όσα παρατηρεί να φαίνονται αντιφατικά ή ακατανόητα.

     

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

        Το λάθος μου είναι ότι προσπαθώ να παρακάμψω τη διαδικασία εκμάθησης που απαιτείται για κάθε περίπλοκο θέμα και να μπω κατευθείαν στις λεπτομέρειες. Έτσι όμως χάνω τις βάσεις και αναγκάζομαι να τις υποκαταστήσω με υποθέσεις.

     

    Στη συγκεκριμένη περίπτωση, η εσφαλμένη υπόθεση είναι ότι η Dispose έχει κάποια ειδική σημασία για το runtime και μάλιστα, ότι μπορεί να καταστρέψει ένα object instance. Επίσης λανθασμένη είναι η υπόθεση ότι για να προσθέσεις μια κλάση Dispose σε μία κλάση πρέπει να κάνεις implement το IDisposable. Η εσφαλμένη υπόθεση βασίστηκε στον τρόπο που έχουν υλοποιηθεί οι μέθοδοι της κλάσης Form.

     

    Η μόνη λύση που έχω βρει σε τέτοιες περιπτώσεις είναι να απορρίψω όσο μπορώ τις βιαστικές υποθέσεις που έχω κάνει και να αρχίσω να διαβάζω από την αρχή για το θέμα που με απασχολεί, προσπαθώντας να μπω στη λογική του θέματος, όχι να προσαρμόσω το θέμα στη δικιά μου λογική.

     

    Στη συγκεκριμένη περίπτωση θα πρότεινα στον infocenter να διαβάσει το «Implementing Finalize and Dispose to Clean Up Unmanaged Resources». Ειδικά στο τέλος, αναφέρει:

    «You should consider not allowing an object to be usable after its Dispose method has been called. Recreating an object that has already been disposed is a difficult pattern to implement.».
    Είναι στην επιλογή του προγραμματιστή μιας κλάσης να την γράψει ώστε να μην χρησιμοποιείται μετά από την κλήση της Dispose.

     

     


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  17-02-2006, 05:10 9809 σε απάντηση της 9799

    Απ: Singleton Form

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

    Ίσως το ερώτημα να είναι και λίγο φιλοσοφικό όπως ανέφερε ο KelMan για το αν θα έπρεπε ή όχι να γίνετε αυτό η εκείνο. Στη συγκεκριμένη περίπτωση αυτό που συζητάμε. Σημασία όμως δεν έχει το τι θα μπορούσε αλλά το τι γίνεται και πως το αντιλαμβανόμαστε αυτό.

    Ευχαριστώ και πάλι όλους για το χρόνο τους.
  •  24-02-2006, 12:58 10080 σε απάντηση της 9045

    Απ: Singleton Form

    Αυτό το description μπορεί να βοηθήσει:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconFinalizeDestructors.asp
Σελίδα 2 από 2 (25 εγγραφές)   < 1 2
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems