Προγραμματισμός

Πώς να χρησιμοποιήσετε το ValueTask σε C #

Ο ασύγχρονος προγραμματισμός χρησιμοποιείται εδώ και αρκετό καιρό τώρα. Τα τελευταία χρόνια, έχει γίνει πιο ισχυρό με την εισαγωγή των λέξεων-κλειδιών ασύγχρονης και αναμονής. Μπορείτε να επωφεληθείτε από τον ασύγχρονο προγραμματισμό για να αυξήσετε την ανταπόκριση και την απόδοση της εφαρμογής σας.

Ο συνιστώμενος τύπος επιστροφής μιας ασύγχρονης μεθόδου στο C # είναι Task. Θα πρέπει να επιστρέψετε το Task εάν θέλετε να γράψετε μια ασύγχρονη μέθοδο που επιστρέφει μια τιμή. Αν θέλετε να γράψετε ένα πρόγραμμα χειρισμού συμβάντων, μπορείτε να επιστρέψετε το κενό. Μέχρι το C # 7.0 μια ασύγχρονη μέθοδος θα μπορούσε να επιστρέψει Task, Task ή άκυρη. Ξεκινώντας με το C # 7.0, μια ασύγχρονη μέθοδος μπορεί επίσης να επιστρέψει το ValueTask (διαθέσιμο ως μέρος του πακέτου System.Threading.Tasks.Extensions) ή ValueTask. Αυτό το άρθρο παρουσιάζει μια συζήτηση για το πώς μπορούμε να εργαστούμε με το ValueTask στο C #.

Για να εργαστείτε με τα παραδείγματα κώδικα που παρέχονται σε αυτό το άρθρο, θα πρέπει να έχετε εγκαταστήσει το Visual Studio 2019 στο σύστημά σας. Εάν δεν έχετε ήδη αντίγραφο, μπορείτε να κατεβάσετε το Visual Studio 2019 εδώ.

Δημιουργήστε ένα έργο εφαρμογής .NET Core κονσόλας στο Visual Studio

Πρώτα απ 'όλα, ας δημιουργήσουμε ένα έργο εφαρμογής .NET Core κονσόλας στο Visual Studio. Υποθέτοντας ότι το Visual Studio 2019 είναι εγκατεστημένο στο σύστημά σας, ακολουθήστε τα βήματα που περιγράφονται παρακάτω για να δημιουργήσετε ένα νέο έργο εφαρμογής .NET Core κονσόλας στο Visual Studio.

  1. Εκκινήστε το Visual Studio IDE.
  2. Κάντε κλικ στο "Δημιουργία νέου έργου".
  3. Στο παράθυρο "Δημιουργία νέου έργου", επιλέξτε "Εφαρμογή κονσόλας (.NET Core)" από τη λίστα των προτύπων που εμφανίζονται.
  4. Κάντε κλικ στο Επόμενο.
  5. Στο παράθυρο "Διαμόρφωση του νέου έργου" που εμφανίζεται στη συνέχεια, καθορίστε το όνομα και την τοποθεσία για το νέο έργο.
  6. Κάντε κλικ στο Δημιουργία.

Αυτό θα δημιουργήσει ένα νέο έργο εφαρμογής .NET Core κονσόλας στο Visual Studio 2019. Θα χρησιμοποιήσουμε αυτό το έργο για να δείξουμε τη χρήση του ValueTask στις επόμενες ενότητες αυτού του άρθρου.

Γιατί να χρησιμοποιήσω το ValueTask;

Μια εργασία αντιπροσωπεύει την κατάσταση κάποιας λειτουργίας, δηλαδή εάν η λειτουργία έχει ολοκληρωθεί, ακυρωθεί και ούτω καθεξής. Μια ασύγχρονη μέθοδος μπορεί να επιστρέψει είτε μια Εργασία είτε ένα ValueTask.

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

Εδώ είναι ακριβώς που το ValueTask έρχεται να σώσει. Το ValueTask παρέχει δύο σημαντικά οφέλη. Πρώτον, το ValueTask βελτιώνει την απόδοση επειδή δεν χρειάζεται κατανομή σωρού και, δεύτερον, είναι εύκολο και ευέλικτο στην εφαρμογή. Επιστρέφοντας το ValueTask αντί του Task από μια ασύγχρονη μέθοδο όταν το αποτέλεσμα είναι άμεσα διαθέσιμο, μπορείτε να αποφύγετε την περιττή επιβάρυνση της κατανομής, καθώς το "T" εδώ αντιπροσωπεύει μια δομή και μια δομή στο C # είναι ένας τύπος τιμής (σε αντίθεση με το "T" στο Task, το οποίο αντιπροσωπεύει μια τάξη).

Το Task και το ValueTask αντιπροσωπεύουν δύο πρωτεύοντες «αναμενόμενους» τύπους στο C #. Σημειώστε ότι δεν μπορείτε να αποκλείσετε ένα ValueTask. Εάν πρέπει να αποκλείσετε θα πρέπει να μετατρέψετε το ValueTask σε μια εργασία χρησιμοποιώντας τη μέθοδο AsTask και, στη συνέχεια, να αποκλείσετε το αντικείμενο αναφοράς εργασίας.

Σημειώστε επίσης ότι κάθε ValueTask μπορεί να καταναλωθεί μόνο μία φορά. Εδώ η λέξη "consume" υπονοεί ότι ένα ValueTask μπορεί να περιμένει ασύγχρονα (αναμονή) τη λειτουργία για να ολοκληρωθεί ή να εκμεταλλευτεί το AsTask για να μετατρέψει ένα ValueTask σε μια εργασία. Ωστόσο, ένα ValueTask θα πρέπει να καταναλώνεται μόνο μία φορά, μετά το οποίο το ValueTask θα πρέπει να αγνοείται.

Παράδειγμα ValueTask σε C #

Ας υποθέσουμε ότι έχετε μια ασύγχρονη μέθοδο που επιστρέφει μια εργασία. Μπορείτε να επωφεληθείτε από το Task.FromResult για να δημιουργήσετε το αντικείμενο Task όπως φαίνεται στο απόσπασμα κώδικα που δίνεται παρακάτω.

δημόσια εργασία GetCustomerIdAsync ()

{

επιστροφή Task.FromResult (1);

}

Το παραπάνω απόσπασμα κώδικα δεν δημιουργεί ολόκληρο το μαγικό μηχάνημα κατάστασης async, αλλά εκχωρεί ένα αντικείμενο εργασίας στο σωρό που διαχειρίζεται. Για να αποφύγετε αυτήν την κατανομή, ίσως θελήσετε να επωφεληθείτε από το ValueTask, όπως φαίνεται στο απόσπασμα κώδικα που δίνεται παρακάτω.

δημόσια ValueTask GetCustomerIdAsync ()

{

επιστροφή νέου ValueTask (1);

}

Το ακόλουθο απόσπασμα κώδικα απεικονίζει μια σύγχρονη εφαρμογή του ValueTask.

 δημόσιο περιβάλλον εργασίας IRepository

    {

ValueTask GetData ();

    }

Η κλάση Repository επεκτείνει τη διεπαφή IRepository και εφαρμόζει τις μεθόδους της όπως φαίνεται παρακάτω.

  δημόσια τάξη αποθετήριο: IR αποθετήριο

    {

δημόσια ValueTask GetData ()

        {

var τιμή = προεπιλογή (T);

επιστροφή νέου ValueTask (τιμή);

        }

    }

Εδώ μπορείτε να καλέσετε τη μέθοδο GetData από την κύρια μέθοδο.

static void Main (συμβολοσειρά [] args)

        {

IR αποθετήριο αποθετήριο = νέο αποθετήριο ();

var result = repository.GetData ();

εάν (αποτέλεσμα. Ολοκληρώθηκε)

Console.WriteLine ("Η λειτουργία ολοκληρώθηκε ...");

αλλού

Console.WriteLine ("Μη ολοκληρωμένη λειτουργία ...");

Κονσόλα.ReadKey ();

        }

Ας προσθέσουμε τώρα μια άλλη μέθοδο στο αποθετήριο μας, αυτή τη φορά μια ασύγχρονη μέθοδο που ονομάζεται GetDataAsync. Εδώ θα μοιάζει η τροποποιημένη διεπαφή IRepository.

δημόσιο περιβάλλον εργασίας IRepository

    {

ValueTask GetData ();

ValueTask GetDataAsync ();

    }

Η μέθοδος GetDataAsync εφαρμόζεται από την κλάση αποθετηρίου όπως φαίνεται στο απόσπασμα κώδικα που δίνεται παρακάτω.

  δημόσια τάξη αποθετήριο: IR αποθετήριο

    {

δημόσια ValueTask GetData ()

        {

var τιμή = προεπιλογή (T);

επιστροφή νέου ValueTask (τιμή);

        }

public async ValueTask GetDataAsync ()

        {

var τιμή = προεπιλογή (T);

περιμένετε Task.Delay (100);

αξία επιστροφής;

        }

    }

Πότε πρέπει να χρησιμοποιήσω το ValueTask στο C #;

Παρά τα οφέλη που παρέχει το ValueTask, υπάρχουν ορισμένες αντισταθμίσεις για τη χρήση του ValueTask αντί του Task. ValueTask είναι ένας τύπος τιμής με δύο πεδία, ενώ το Task είναι ένας τύπος αναφοράς με ένα μόνο πεδίο. Ως εκ τούτου, η χρήση ValueTask σημαίνει εργασία με περισσότερα δεδομένα, καθώς μια μέθοδος κλήσης θα επιστρέψει δύο πεδία δεδομένων αντί για ένα. Επίσης, εάν περιμένετε μια μέθοδο που επιστρέφει ένα ValueTask, η μηχανή κατάστασης για αυτήν την ασύγχρονη μέθοδο θα είναι επίσης μεγαλύτερη - γιατί θα έπρεπε να φιλοξενήσει μια δομή που περιέχει δύο πεδία αντί για μία μόνο αναφορά στην περίπτωση μιας εργασίας.

Επιπλέον, εάν ο καταναλωτής μιας ασύγχρονης μεθόδου χρησιμοποιεί το Task.WhenAll ή το Task.WhenAny, η χρήση του ValueTask ως τύπου επιστροφής σε μια ασύγχρονη μέθοδο μπορεί να γίνει δαπανηρή. Αυτό συμβαίνει επειδή θα πρέπει να μετατρέψετε το ValueTask σε Task χρησιμοποιώντας τη μέθοδο AsTask, η οποία θα επιβαρύνει μια κατανομή που θα μπορούσε εύκολα να αποφευχθεί εάν είχε χρησιμοποιηθεί αρχικά μια κρυφή εργασία.

Εδώ είναι ο κανόνας του αντίχειρα. Χρησιμοποιήστε το Task όταν έχετε ένα κομμάτι κώδικα που θα είναι πάντα ασύγχρονο, δηλαδή όταν η λειτουργία δεν θα ολοκληρωθεί αμέσως. Επωφεληθείτε από το ValueTask όταν το αποτέλεσμα μιας ασύγχρονης λειτουργίας είναι ήδη διαθέσιμο ή όταν έχετε ήδη αποθηκευμένο αποτέλεσμα. Είτε έτσι είτε αλλιώς, θα πρέπει να εκτελέσετε την απαραίτητη ανάλυση απόδοσης πριν εξετάσετε το ValueTask

Πώς να κάνετε περισσότερα στο C #:

  • Πώς να χρησιμοποιήσετε το αμετάβλητο στο C
  • Πώς να χρησιμοποιήσετε const, μόνο για ανάγνωση και στατικό σε C #
  • Πώς να χρησιμοποιήσετε σχολιασμούς δεδομένων στο C #
  • Πώς να εργαστείτε με GUID στο C # 8
  • Πότε να χρησιμοποιήσετε μια αφηρημένη τάξη εναντίον διεπαφής στο C #
  • Πώς να εργαστείτε με το AutoMapper στο C #
  • Πώς να χρησιμοποιήσετε τις εκφράσεις λάμδα στο C #
  • Πώς να συνεργαστείτε με τους αντιπροσώπους Action, Func και Predicate στο C #
  • Πώς να συνεργαστείτε με εκπροσώπους στο C #
  • Πώς να εφαρμόσετε έναν απλό καταγραφέα στο C #
  • Πώς να εργαστείτε με χαρακτηριστικά στο C #
  • Πώς να εργαστείτε με το log4net στο C #
  • Πώς να εφαρμόσετε το μοτίβο σχεδίασης αποθετηρίου στο C #
  • Πώς να εργαστείτε με προβληματισμό στο C #
  • Πώς να εργαστείτε με το σύστημα παρακολούθησης αρχείων στο C #
  • Πώς να εκτελέσετε τεμπέλης αρχικοποίηση στο C #
  • Πώς να εργαστείτε με το MSMQ στο C #
  • Πώς να εργαστείτε με μεθόδους επέκτασης στο C #
  • Πώς να μας εκφράσεις λάμδα στο C #
  • Πότε να χρησιμοποιήσετε την ευμετάβλητη λέξη-κλειδί στο C #
  • Πώς να χρησιμοποιήσετε τη λέξη-κλειδί απόδοσης στο C #
  • Πώς να εφαρμόσετε τον πολυμορφισμό στο C #
  • Πώς να δημιουργήσετε τον δικό σας προγραμματιστή εργασιών στο C #
  • Πώς να εργαστείτε με το RabbitMQ στο C #
  • Πώς να εργαστείτε με μια πλειάδα στο C #
  • Εξερεύνηση εικονικών και αφηρημένων μεθόδων στο C #
  • Πώς να χρησιμοποιήσετε το Dapper ORM στο C #
  • Πώς να χρησιμοποιήσετε το μοτίβο σχεδιασμού flyweight στο C #