.NET Winforms: Μπορεί το χρόνο εκτέλεσης διαθέτει λαβή μιας φόρμας από κάτω μου;

ψήφοι
13

Η σημερινή δήλωση του SendMessage πάνω σε PInvoke.net είναι:

[DllImport(user32.dll, CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, 
      IntPtr wParam, IntPtr lParam);

Σημείωση: Η hWnd δεν είναι πλέον μια IntPtr , και έχει αντικατασταθεί με HandleRef . Μια πολύ χαλαρή εξήγηση για την αλλαγή δίνεται:

Μπορείτε να αντικαταστήσετε «hWnd» με «IntPtr» αντί για «HandleRef». Ωστόσο, παίρνετε ένα κίνδυνο στο να γίνει αυτό - μπορεί να προκαλέσει τον κωδικό σας για να συντρίψει με τις συνθήκες του αγώνα. Το .NET runtime μπορεί και θα διαθέσει το παράθυρό σας χειρίζεται έξω από κάτω από το μήνυμά σας - που προκαλεί όλα τα είδη των δυσάρεστα προβλήματα!

Κάποιος wiki'd μια ερώτηση συνέχισης:

Ερώτηση: Δεν είναι δυνατή αυτή η τελευταία το θέμα να αντιμετωπιστεί με παράταξης, ειδικά καρφώνει;

Και κάποιος απάντησε:

Απάντηση: Μπορείτε να χρησιμοποιήσετε GC.KeepAlive () αμέσως μετά την SendMessage () με το αντικείμενο έντυπο ως παράμετρος για την KeepAlive ().

Όλη αυτή η «διάθεση φόρμα σας κάτω από σας» φαίνεται περίεργο για μένα. SendMessage είναι μια σύγχρονη κλήση. Δεν θα επιστρέψει μέχρι έως ότου ολοκληρωθεί η επεξεργασία της έστειλε μήνυμα.

Η επίπτωση τότε είναι ότι μια λαβή μορφής μπορεί να καταστραφεί σε οποιαδήποτε στιγμή. Για παράδειγμα:

private void DoStuff()
{
   //get the handle
   IntPtr myHwnd = this.Handle;


   //Is the handle still valid to use?
   DoSomethingWithTheHandle(myHwnd); //handle might not be valid???


   //fall off the function
}

Αυτό σημαίνει ότι η λαβή παράθυρο μπορεί να γίνει άκυρη από τη στιγμή εγώ και ο χρόνος που η μέθοδος τελειώνει χρησιμοποιήσω;


Ενημέρωση One

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

private IntPtr theHandle = IntPtr.Zero;

private void DoStuff()
{
   MyForm frm = new MyForm())

   theHandle = frm.Handle;

   //Note i didn't dispose of the form.
   //But since it will be unreferenced once this method ends
   //it will get garbage collected,
   //making the handle invalid
}

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

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

Με άλλα λόγια, δεν μπορώ να φανταστώ ότι η κλήση:

IntPtr hWnd = this.Handle;

θα αποτρέψει τώρα αυτό από το να απορριμμάτων που συγκεντρώνονται.


Ενημέρωση Δύο

Δεν μπορώ να φανταστώ έχει ένα παράθυρο χειριστεί περίπου θα κρατήσει μια φόρμα από το να απορριμμάτων που συγκεντρώνονται. δηλαδή:

Clipboard.AsText = this.Handle.ToString();
IntPtr theHandle = (IntPtr)(int)Clipboard.AsText;

Απάντηση

Αλλά αυτά είναι illevant σημεία - το αρχικό ερώτημα παραμένει:

Μπορεί το χρόνο εκτέλεσης διαθέτει λαβή μιας φόρμας από κάτω μου;

Η απάντηση, αποδεικνύεται, δεν είναι. Το runtime δεν θα διαθέσει μια μορφή έξω από κάτω από μένα. Αυτό θα διαθέσει ένα unreferenced μορφή - αλλά unreferenced μορφές δεν είναι κάτω από μένα. «Υπό Me» σημαίνει έχω μια αναφορά στη φόρμα.

Από την άλλη πλευρά, υποκείμενα των Windows παράθυρο λαβή ενός αντικειμένου έντυπο μπορεί να καταστρέψει έξω από κάτω από μένα (και πραγματικά πώς θα μπορούσε να μην - χερούλια παράθυρο δεν είναι αναφορά υπολογίζονται - ούτε θα πρέπει να είναι):

IntPtr hwnd = this.Handle;
this.RightToLeft = RightToLeft.Yes;
//hwnd is now invalid

Είναι επίσης σημαντικό να σημειωθεί ότι HandleRef δεν θα βοηθήσει στην πρόληψη των προβλημάτων που προκαλούνται από τη δημιουργία αντικειμένου περιτυλίγματα γύρω χειρίζεται παράθυρο των Windows:

Λόγος 1 Εάν ένα αντικείμενο έντυπο καταστρέφεται επειδή δεν είχε σχέση με αυτό - τότε είστε απλά ηλίθιος για να προσπαθήσουμε να μιλήσει σε μια μορφή που από δικαιώματα υπάρχουν θα πρέπει πλέον. Ακριβώς επειδή το GC δεν έχει πάρει γύρω από αυτό ακόμα δεν σας κάνει έξυπνες - θα σας κάνει να τυχερός. Μια HandleRef είναι ένα hack για να κρατήσει μια αναφορά στη φόρμα. Αντί να χρησιμοποιούν:

HandleRef hr = new HandleRef(this, this.Handle);
DoSomethingWithHandle(this.Handle);

θα μπορούσε εύκολα να χρησιμοποιήσετε:

Object o = this;
DoSomethingWithHandle(this.Handle);

Λόγος 2 HandleRef δεν θα εμποδίσει μια φόρμα από την εκ νέου δημιουργία είναι υποκείμενες λαβή παράθυρο, π.χ:

HandleRef hr = new HandleRef(this, this.Handle);
this.RightToLeft = RightToLeft.Yes;
//hr.Hande is now invalid

Έτσι, ενώ η αρχική τροποποίησης των SendMessage σε P / Invoke είχε επισημάνει το πρόβλημα, η λύση του δεν είναι λύση.

Δημοσιεύθηκε 09/12/2008 στις 17:27
πηγή χρήστη
Σε άλλες γλώσσες...                            


1 απαντήσεις

ψήφοι
3

Συχνά, όταν καλείτε SendMessage, κάνετε τόσο από άλλο νήμα ή τουλάχιστον ένα άλλο συστατικό ξεχωριστά από το έντυπο σας. Υποθέτω ότι το σημείο που γίνεται είναι ότι μόνο και μόνο επειδή έχετε μια IntPtr η οποία σε ένα σημείο περιείχε ένα έγκυρο παράθυρο λαβή, δεν μπορείτε να υποθέσουμε ότι εξακολουθεί να είναι έγκυρη.

Ας υποθέσουμε ότι είχατε αυτή την κατηγορία:

class MyClass {
   IntPtr hwnd;
   public MyClass(IntPtr hwnd) {
      this.hwnd = hwnd;
   }
   ...

   private void DoStuff()
   {
       //n.b. we don't necessarily know if the handle is still valid
       DoSomethingWithTheHandle(hwnd);
   }
}

και κάπου αλλού:

 private void DoOtherStuff() {
     Form f = new Form();
     mc = new MyClass(f.Handle);
 }

τότε γιατί fμπήκε στον αγωνιστικό χώρο του πεδίου εφαρμογής, της Disposeβούλησης τελικά να καλείται από την finalizer GC. Γι 'αυτό ίσως χρειαστεί να χρησιμοποιήσει Gc.KeepAliveσε αυτό το είδος της κατάστασης. fπρέπει να παραμείνουν ζωντανοί μέχρι να mcολοκληρωθεί με τη λαβή.

Απαντήθηκε 09/12/2008 στις 17:48
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more