Έχω διαβάσει πολλά εισαγωγικά άρθρα σχετικά με τον τρόπο ενημέρωσης της κύριας διεπαφής στο νήμα παρασκηνίου και τα περισσότερα από αυτά χρησιμοποιούν Control.Invoke και Control.BeginInvoke. Αυτές είναι καλές λύσεις, αλλά υπάρχουν δύο προβλήματα:
1. Πρέπει να κάνετε αναφορά στο System.Windows.Forms και, στη συνέχεια, να χρησιμοποιήσετε το System.Windows.Forms
2. Η δομή του κώδικα είναι σχετικά ακατάστατη. (Στην πραγματικότητα, αυτό προκαλείται επίσης από το #1)
Η Microsoft προσφέρει μια άλλη πιο κομψή λύση, η οποία είναι το System.Threading. SynchronizationContext。 Όπως μπορείτε να δείτε, δεν είναι στο namesapce System.Windows.Forms, οπότε μπορούμε να το χρησιμοποιήσουμε δικαιωματικά στο BusinessLaryer, στο Controler, ακόμη και σε λειτουργικές μονάδες.
Και είναι πολύ βολικό στη χρήση, χρειάζεται μόνο να εστιάσετε στις ακόλουθες δύο μεθόδους:
1. Αποστολή: Στέλνει ένα αίτημα ενημέρωσης διεπαφής στο κύριο νήμα, αποκλείοντας το τρέχον νήμα μέχρι να επιστρέψει.
2. Δημοσίευση: Στέλνει ένα αίτημα ενημέρωσης διεπαφής στο κύριο νήμα χωρίς να αποκλείει το τρέχον νήμα.
Στην πραγματικότητα, είναι όλες η ίδια μέθοδος, εκτός από το ότι η αποστολή είναι σύγχρονη και η ανάρτηση είναι ασύγχρονη
Πριν από τη φόρμα Form1 = new Form1(), το αντικείμενο SynchronizationContext ήταν κενό και όταν δημιουργήθηκε η φόρμα Form1, το αντικείμενο SynchronizationContext προσαρτήθηκε σε αυτό το νήμα. Έτσι, η απάντηση είναι ότι όταν δημιουργείται το αντικείμενο Control, δημιουργείται επίσης το αντικείμενο SynchronizationContext και προσαρτάται στο νήμα. Όλα όταν χρησιμοποιείτε τη φόρμα InitializeComponent(); Μόλις γίνει αυτό, μπορεί να πάρει ένα αντικείμενο που δεν είναι NULL
Τέλος, η διαφορά μεταξύ των μεθόδων Sendt() και Post() του SynchronizationContext:
Η Send() υλοποιείται καλώντας απλώς τον εκπρόσωπο στο τρέχον νήμα (σύγχρονη κλήση). Δηλαδή, το νήμα διεπαφής χρήστη καλείται απευθείας στο υπονήμα για εκτέλεση και το υπονήμα θα συνεχίσει να εκτελείται μετά την ολοκλήρωση της εκτέλεσης του νήματος διεπαφής χρήστη.
Η Post() υλοποιείται καλώντας έναν εκπρόσωπο στο χώρο συγκέντρωσης νημάτων (ασύγχρονη κλήση). Αυτό συμβαίνει επειδή το υπονήμα θα βρει ένα νήμα από το thread pool για να συντονίσει το νήμα διεπαφής χρήστη και το δευτερεύον νήμα θα εκτελέσει απευθείας τον δικό του κώδικα χωρίς να περιμένει να ολοκληρωθεί το νήμα διεπαφής χρήστη. Κωδικός δοκιμής:
Έκβαση:
Κύριο νήμα διεπαφής χρήστη: 1 Νήμα: 5 SynchContext:1
Περίληψη:Το αντικείμενο SynchronizationContext στο νήμα διεπαφής χρήστη, είτε καλείται στο κύριο νήμα είτε στο νήμα, θα εκτελεστεί στο κύριο νήμα, επομένως όταν υπάρχει πολύς χρονοβόρος κώδικας, θα προκαλέσει πάγωμα της διεπαφής διεπαφής χρήστη ή ψεύτικο θάνατο!
Στην πραγματικότηταΤο νήμα περιβάλλοντος εργασίας χρήστη δεν χρησιμοποιεί την κλάση SynchronizationContext, αλλά το WindowsFormsSynchronizationContextΑυτό το Dongdong.
Πηγαίος κώδικας System.Threading.SynchronizationContext:
Πηγαίος κώδικας WindowsFormsSynchronizationContext:
|