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

 

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

=Nothing ή Dispose

Îåêßíçóå áðü ôï ìÝëïò axaros. Τελευταία δημοσίευση από το μέλος axaros στις 24-08-2005, 09:07. Υπάρχουν 16 απαντήσεις.
Σελίδα 1 από 2 (17 εγγραφές)   1 2 >
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  28-06-2005, 16:19 3155

    =Nothing ή Dispose

    και γιατί ανύσηχοι;
    Πάνος Αβραμίδης
  •  28-06-2005, 16:44 3156 σε απάντηση της 3155

    Re: =Nothing ή Dispose

    Είναι πολύ διαφορετικά πράγματα. Μπορεί το =Nothing/=null μόνο του, αλλά μπορείς να γίνει και με συνδυασμό με το .Dispose().

    Όταν κάνεις κάτι απλά =Nothing/=null, το μαρκάρεις ουσιαστικά ότι έχεις τελειώσει μαζί του. Αυτό δεν σημαίνει ότι φεύγει και από την μνήμη/stack. Θα περιμένει να τρέξει Garbage Collector για να το απομακρύνει. Αν αυτό χρησιμοποιεί εξωτερικά resources, ένα connection σε SQL Server, θα το απελευθερώσει.

    Το .Dispose() πάει ένα βήμα παραπάνω και απελευθερώνει και τοπικά resources που χρησιμοποιούνται. Buffers που χρησιμοποιήθηκαν...

    Δες και αυτά εδώ τα
    posts... Είναι παρεμφερές με αυτό που θες που ρωτάς...
     
    Και διάβασε το
    10η εντολή! Big Smile


    George J.

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

    Yes [Y] Re: =Nothing ή Dispose

    Όπως πάντα Σπαρτιάτης και to the point ...
    Σε πάω Δάσκαλε !!!!Big Smile

    Ευχαριστώ γι' άλλη μια φορά ...



    Πάνος Αβραμίδης
  •  28-06-2005, 16:52 3158 σε απάντηση της 3156

    Re: =Nothing ή Dispose

    Να το πώ αλλιώς εγώ;

    Αν το object σου δεν περιέχει references άλλα objects τότε το =nothing θα μηδενίσει το reference σε αυτό και θα το "μαζέψει" ο GC στον επόμενο κύκλο του.

    Αν το object σου περιέχει references σε άλλα objects και ΙΔΙΑΙΤΕΡΑ αν κάποια από αυτά είναι unmanaged, τότε αυτά ζουν ωσπου το object σου να "μαζευτεί" από τον garbage collector (ειδικά για τα unmanaged, δεν είμαι σίγουρος οτι πεθαίνουν εκεί). Αρα, αν έχεις ένα "παχύ" object με πολλά άλλα objects π.χ. που περιέχονται σε ένα arraylist ή ένα hashtable ή ένα collection βρε αδελφέ και αυτά με τη σειρά τους ενδέχεται να περιέχουν άλλα objects κλπ, δημιουργείται μια "αλυσίδα" την οποία μπορεί να θέλεις να καταργήσεις και να εξαφανίσεις όσο το δυνατόν πιό γρήγορα αφού την χρησιμοποιήσεις και κάνεις τη δουλειά σου.

    Εκεί, dispose.

    Παραδειγμα: Serviced components. Δεν θέλουμε να τα έχουμε να γυρνάνε γύρω γυρω αφου τελειώσουμε την κλήση μας (αρα και τη δουλειά μας). Αρα τα κάνουμε dispose οσο το δυνατόν ταχύτερα. Αν είναι pooled, ξαναμπαίνουν στο pool και είναι διαθέσιμα για την επόμενη κλήση.




    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  28-06-2005, 17:00 3160 σε απάντηση της 3158

    Re: =Nothing ή Dispose

     cap wrote:

    Να το πώ αλλιώς εγώ;

    Αν το object σου δεν περιέχει references άλλα objects τότε το =nothing θα μηδενίσει το reference σε αυτό και θα το "μαζέψει" ο GC στον επόμενο κύκλο του.



    Ευχαριστώ και εσένα Σωτήρη ...
    Ο Garbage Collector επιδέχεται ρυθμίσεις ;
    Πάνος Αβραμίδης
  •  28-06-2005, 17:04 3161 σε απάντηση της 3160

    Re: =Nothing ή Dispose

    Γενικά επιδέχεται ρυθμίσεις, (μπορείς να χρησιμοποιήσεις τη GC.Collect για να κάνεις force τον κύκλο του Garbage Collector αλλα ΔΕΝ προτείνεται - ειναι αρκετά αποδοτικός ως έχει αν τον αφήσεις να λειτουργήσει μόνος του).

    Σου παραθέτω το εξής πολύ χρήσιμο άρθρο για να δεις περισσότερα (ο συγκεκριμένος τα λεει πολύ καλύτερα και λεπτομερέστερα από ο,τι τα είπα εγω):
    http://blogs.msdn.com/clyon/archive/2004/09/21/232445.aspx



    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  28-06-2005, 17:08 3162 σε απάντηση της 3161

    Re: =Nothing ή Dispose

    Επιπρόσθετα:

    Λόγω του οτι τo dispose γενικά ΔΕΝ είναι threadsafe, υπάρχει ένα common pattern που ακολουθείται για να κάνεις dispose ένα object. Σου παραθέτω τον κώδικα παρακάτω:

    #Region " Constructors / Destructors "

     

     

      '/// <summary>

      '/// Default constructor.

      '/// </summary>

      Public Sub New()

     

        'TODO: Insert Necessary object construction code

       

      End Sub

     

     

      '/// <summary>

      '/// Standard Dispose Implementation Pattern, part II.

      '/// Overridable and Overloaded Dispose procedure is called by both

      '/// Dispose and Finalize Not Overridable procedures.

      '/// </summary>

      '/// <param name="p_bDisposing">

      '/// If its value is True, then this procedure is called by User calling

      '/// Dispose(). Else it is called by System calling Finalize().

      '/// </param>

      '/// <returns></returns>

      Protected Overridable Overloads Sub Dispose(ByVal p_bDisposing As Boolean)

     

        'User called Dispose(True)

        If (p_bDisposing = True) Then

          'TODO: Free other state (managed objects).

        End If

     

        'TODO: Free own state (unmanaged objects).

        'Set large fields to null, etc.

     

      End Sub

     

     

      '/// <summary>

      '/// Standard Dispose Implementation Pattern, part I.

      '/// Not Overridable Dispose procedure just calls overloaded Dispose(True).

      '/// </summary>

      Public Overloads Sub Dispose() Implements System.IDisposable.Dispose

     

        'Call common overloaded and overridable disposing procedure

        'to perform all necessary finalization actions.

        Dispose(True)

     

        'Remove this object from the Finalization Queue,

        'because Dispose procedure has already been called.

        GC.SuppressFinalize(Me)

     

      End Sub

     

     

      '/// <summary>

      '/// Standard Dispose Implementation Pattern, part III.

      '/// Not Overridable Finalize procedure just calls Dispose(False).

      '/// </summary>

      Protected Overrides Sub Finalize()

     

        'Simply call Dispose(False), because user has not already

        'called Dispose () to perform object finalization process.

        Dispose(False)

     

      End Sub

     

     

    #End Region


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  19-08-2005, 10:42 4411 σε απάντηση της 3162

    Απ:Re: =Nothing ή Dispose

    Παρεπιπτόντως βρήκα το εξής σε κάποιο post για VB.NET 2005:

    Public Class Class1

        Public Sub Go()
            Using sw As StreamWriter = New StreamWriter("C:\hey.txt")
                sw.Write("HEY")
            End Using
        End Sub

    End Class

    via MSDN: "The using statement obtains one or more resources, executes a statement, and then disposes of the resource."

     

     


    Πάνος Αβραμίδης
  •  19-08-2005, 10:50 4412 σε απάντηση της 4411

    Απ:Re: =Nothing ή Dispose

    Πανο, πολύ σωστά. Μας το είχαν δείξει και στο DevDays. Το Using, το οποίο κληρονομήθηκε από τη C#, κάνει ακριβως αυτό που περιγράφεις.

    Αρα λοιπον για να επανέλθουμε στο αρχικο θέμα, το dispose χρησιμοποιείται γενικά όταν υπάρχει λόγος. Θα δείς οτι ακόμα και στο ίδιο το framework, όλα τα objects που φτιάχνεις δεν διαθέτουν dispose method. Μονο αυτά για τα οποία υπάρχει λόγος.

    Ενα θέμα είναι λοιπόν πότε κάνουμε implement το idisposable interface εντός της κλάσης μας και πότε χρησιμοποιούμε dispose εξωτερικά. Ενας εμπειρικός κανόνας: Αν το object διαθέτει dispose method, καλό είναι να τη χρησιμοποιήσουμε.

    Αν βέβαια χρησιμοποιήσουμε, όπως λες παραπάνω, το Using, δεν χρειάζεται να ανησυχούμε για αυτό.


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  19-08-2005, 11:30 4415 σε απάντηση της 4412

    Απ:Re: =Nothing ή Dispose

    Σωτήρη από περιέργεια : σε αυτή την περίπτωση το Dispose είναι Thread safe;
    Πάνος Αβραμίδης
  •  19-08-2005, 11:38 4418 σε απάντηση της 4415

    Απ:Re: =Nothing ή Dispose

    Εννοείς με το using; Το thread-safety του dispose δεν εξαρτάται, σύμφωνα βέβαια με τις φτωχές μου γνώσεις, τις οποίες μπορεί καθένας να διορθώσει ελεύθερα, από την ΚΛΗΣΗ του dispose method αλλά από το πώς είναι υλοποιημένο το ίδιο το dispose method. Εξ'ου και το pattern που αναφερεται σε προηγούμενη απάντηση στο post.

    Αρα, αν το dispose method έχει υλοποιηθεί λαμβάνοντας υπόψη του το thread-safety, τότε χρησιμοποιώντας το using είσαι εξ'όρισμού thread safe, μια και το using δεν κάνει τίποτα άλλο από το να καλεί την dispose method του αντικειμένου που χρησιμοποιείται.

     


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  19-08-2005, 11:44 4419 σε απάντηση της 4418

    Απ:Re: =Nothing ή Dispose

    Σωτήρη σε ευχαριστώ θερμά !!!!
    Στη διάθεση σας και ένα ακόμη σχετικό link με το θέμα : http://www.devcity.net/Articles/93/gc_manage.aspx


    Πάνος Αβραμίδης
  •  19-08-2005, 13:14 4424 σε απάντηση της 4412

    Απ:Re: =Nothing ή Dispose

    Παιδιά εγώ το θέμα το αντιμετωπίζω ως εξης:

    • Κατ' αρχήν δεν καλώ ποτέ μόνος μου την Dispose(). Την καλεί στην ώρα της ο Garbage Collector. Τελεία.
    • Πότε είναι η ώρα της; Όταν δεν υπάρχει πουθενά κανένα άλλο reference για το συγκεκριμένο object.
    • Επίσης δεν φτιάχνω ποτέ Dispose method (αφήνω δηλαδή το inherited implementation να τρέχει),

    ...ΕΚΤΟΣ ΕΑΝ....

    έχω ο,τιδήποτε unmanaged μέσα στην class μου (π.χ. όταν έχω χρησιμοποιήσει com interop για να μιλήσω με com components) οπότε είναι απαραίτητο να κάνω implement την Dispose. Σε κάθε άλλη περίπτωση δεν χρειάζεται να ανησυχείς για τίποτα. Οτιδήποτε είναι managed το κάνει ο garbage collector μόνος του. Ο,τιδήποτε ΔΕΝ είναι managed το καθαρίζεις μόνος σου στην Dispose (την οποία δεν την καλείς εσύ πουθενά αλλά την καλεί ο Garbage Collecor μέσω της Finalize (η οποία είναι αντίστοιχη του destructor που ξέραμε στην c++).

    Ο μόνος λόγος να implementάρεις και να καλέσεις μόνος σου την Dispose είναι όταν για κάποιο λόγο "βιάζεσαι" να ελευθερώσεις κάποια resources (συνήθως unmanaged) τα οποία δεν μπορείς να περιμένεις τον garbage collector να τα ελευθερώσει στην πρώτη ευκαιρία.

    Π.χ. έχεις ανοικτά connections με COM objects για να  "μιλάς" με μια άλλη εφαρμογή που ήδη τρέχει ταυτοχρόνως ενώ εσύ κλείνεις την δικιά σου εφαρμογή. Θέλεις να κλείσεις τα connections αυτά αμέσως για να αποφύγεις π.χ. ένα GPF που μπορεί να προκαλέσει η άλλη εφαρμογή αν δεν γίνει η αποδέσμευση των COM που χρησιμοποιείς εγκαίρως και με τη σειρά που θέλεις. Καλείς την Dispose επιτόπου να τα κλείσει. Αν την καλέσεις ως Disposed(true) θα κάνει το ίδιο και για τα managed resources που χρησιμοποιεί, οπότε αν κι εκείνα με την σειρά τους έχουν unmanaged resources θα τα απελευθερώσουν αμέσως κ.ο.κ....

    Δεν ξεχνάς ποτέ στην Dispose (όποτε την κάνεις implement) να βάλεις στο τέλος μια κλήση στην GC.SuppressFinalize(this); ώστε να μην πάει ο garbage collector να ξανακάνει την δουλειά και "σπάσει τα μούτρα του".

    Άρα γενικά, δεν ανησυχείς αν δεν έχεις ανοικτά unmanaged resources. Αν έχεις, τότε κάνεις ότι λέει στο VB παράδειγμά του ο cap σε παραπάνω post. Επίσης αν έχεις .NET Framwork SDK (MSDN) στο PC σου δες αυτό το link ή ψάξε στο MSDN για το topic με θέμα "Implementing a Dispose Method". Ο παρακάτω κώδικας σε C# είναι copy/paste από το παράδειγμα που έχει εκεί...

    // Design pattern for the base class.
    // By implementing IDisposable, you are announcing that instances
    // of this type allocate scarce resources.
    public class BaseResource: IDisposable
    {
       // Pointer to an external unmanaged resource.
       private IntPtr handle;
       // Other managed resource this class uses.
       private Component Components;
       // Track whether Dispose has been called.
       private bool disposed = false;
    
       // Constructor for the BaseResource object.
       public BaseResource()
       {
          // Insert appropriate constructor code here.
       }
    
       // Implement IDisposable.
       // Do not make this method virtual.
       // A derived class should not be able to override this method.
       public void Dispose()
       {
          Dispose(true);
          // Take yourself off the Finalization queue 
          // to prevent finalization code for this object
          // from executing a second time.
          GC.SuppressFinalize(this);
       }
    
       // Dispose(bool disposing) executes in two distinct scenarios.
       // If disposing equals true, the method has been called directly
       // or indirectly by a user's code. Managed and unmanaged resources
       // can be disposed.
       // If disposing equals false, the method has been called by the 
       // runtime from inside the finalizer and you should not reference 
       // other objects. Only unmanaged resources can be disposed.
       protected virtual void Dispose(bool disposing)
       {
          // Check to see if Dispose has already been called.
          if(!this.disposed)
          {
             // If disposing equals true, dispose all managed 
             // and unmanaged resources.
             if(disposing)
             {
                // Dispose managed resources.
                Components.Dispose();
             }
             // Release unmanaged resources. If disposing is false, 
             // only the following code is executed.
             CloseHandle(handle);
             handle = IntPtr.Zero;
             // Note that this is not thread safe.
             // Another thread could start disposing the object
             // after the managed resources are disposed,
             // but before the disposed flag is set to true.
             // If thread safety is necessary, it must be
             // implemented by the client.
    
          }
          disposed = true;         
       }
    
       // Use C# destructor syntax for finalization code.
       // This destructor will run only if the Dispose method 
       // does not get called.
       // It gives your base class the opportunity to finalize.
       // Do not provide destructors in types derived from this class.
       ~BaseResource()      
       {
          // Do not re-create Dispose clean-up code here.
          // Calling Dispose(false) is optimal in terms of
          // readability and maintainability.
          Dispose(false);
       }
    
       // Allow your Dispose method to be called multiple times,
       // but throw an exception if the object has been disposed.
       // Whenever you do something with this class, 
       // check to see if it has been disposed.
       public void DoSomething()
       {
          if(this.disposed)
          {
             throw new ObjectDisposedException();
          }
       }
    }
    
    // Design pattern for a derived class.
    // Note that this derived class inherently implements the 
    // IDisposable interface because it is implemented in the base class.
    public class MyResourceWrapper: BaseResource
    {
       // A managed resource that you add in this derived class.
       private ManagedResource addedManaged;
       // A native unmanaged resource that you add in this derived class.
       private NativeResource addedNative;
       private bool disposed = false;
    
      // Constructor for this object.
       public MyResourceWrapper()
       {
          // Insert appropriate constructor code here.
       }
    
       protected override void Dispose(bool disposing)
       {
          if(!this.disposed)
          {
             try
             {
                if(disposing)
                {
                   // Release the managed resources you added in
                   // this derived class here.
                   addedManaged.Dispose();         
                }
                // Release the native unmanaged resources you added
                // in this derived class here.
                CloseHandle(addedNative);
                this.disposed = true;
             }
             finally
             {
                // Call Dispose on your base class.
                base.Dispose(disposing);
             }
          }
       }
    }
    
    // This derived class does not have a Finalize method
    // or a Dispose method without parameters because it inherits 
    // them from the base class.
    

    αυτά κι από εμένα...

    Φιλικά
    rousso


    rousso
  •  19-08-2005, 13:42 4429 σε απάντηση της 4424

    Απ:Re: =Nothing ή Dispose

    Γιαννη, σωστά αυτά που λές. Θα σου πώ όμως άλλη μία περίπτωση στην οποία θα ήθελε κάποιος να καλεί μόνος του τη dispose:

    Εχεις ένα composite object. Περιέχει εκατοντάδες μικρά collections τα οποία τα χρησιμοποιεί μόνο αυτό. Φορτώνεις συνεπώς στη μνήμη ένα "παχύ" object το οποίο το θέλεις για να κάνεις συγκεκριμένες εργασίες. Θελεις να το ξεφορτωθείς όσο πιό γρήγορα μπορείς.

    Επίσης εγώ θα διαφωνήσω με τη λογική του GC για τα objects τα οποία έχουν dispose. Αν υπάρχει, την καλώ ακριβώς όταν τελειώσω τη δουλειά που κάνω με αυτά. Πιστεύω οτι είναι πιό αποτελεσματικο, ειδικά σε ado.net objects. Αυτή είναι όμως μια υποκειμενική άποψη και ανοιχτή συνεπώς σε κριτική.

     

     


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  23-08-2005, 10:26 4526 σε απάντηση της 4429

    Απ: Απ:Re: =Nothing ή Dispose

    Να ρωτήσω και κάτι άλλο :
    Πως περνάει ένα object από το generation 0 έως το (τελευταίο) 2 του GC;


    Πάνος Αβραμίδης
Σελίδα 1 από 2 (17 εγγραφές)   1 2 >
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems