Υποστήριξη ταυτοχρονισμού του πάγκου εργασίας

Είδαμε ότι το πλαίσιο περιβάλλοντος χρήστη JFace παρέχει βασική υποστήριξη για την εμφάνιση της προόδου εργασιών σε ένα πλαίσιο διαλόγου (δείτε την ενότητα Μακρόχρονες λειτουργίες για λεπτομέρειες). Στην ενότητα Υποδομή ταυτοχρονισμού, εξετάσαμε την υποστήριξη περιβάλλοντος εκτέλεσης πλατφόρμας για ταυτοχρονισμό και μακρόχρονες λειτουργίες. Τώρα θα εξετάσουμε τον τρόπο με τον οποίο το περιβάλλον χρήστη της πλατφόρμας βελτιώνει αυτή την υποδομή στο πακέτο org.eclipse.ui.progress. Αυτό το πακέτο παρέχει το περιβάλλον χρήστη για την εμφάνιση της προόδου εργασιών στον πάγκο εργασίας και ορίζει επιπρόσθετη υποστήριξη για εργασίες που εκτελούνται στο νήμα περιβάλλοντος χρήστη.

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


Δεδομένου ενός περιβάλλοντος όπου αρκετά μπορούν να συμβαίνουν ταυτόχρονα, ένας χρήστης χρειάζεται τα ακόλουθα:

Υπηρεσία προόδου

Η υπηρεσία προόδου του πάγκου εργασίας (IProgressService) αποτελεί την κύρια διεπαφή της υποστήριξης προόδου του πάγκου εργασίας. Μπορεί να ληφθεί από τον πάγκο εργασίας και κατόπιν να χρησιμοποιηθεί για την εμφάνιση της προόδου τόσο για τις λειτουργίες στο παρασκήνιο, όσο και για τις λειτουργίες που εκτελούνται στο νήμα του περιβάλλοντος χρήστη. Ο κύριος στόχος αυτής της κλάσης είναι να παρέχει μια ολοκληρωμένη επιλογή για την εκτέλεση λειτουργιών, ώστε οι προγραμματιστές πρόσθετων λειτουργιών να μην χρειάζεται να αποφασίζουν ποιος μηχανισμός θα πρέπει να χρησιμοποιηθεί για την εμφάνιση της προόδου σε μια δεδομένη κατάσταση. Ένα άλλο πλεονέκτημα είναι ότι το πλαίσιο διαλόγου προόδου που εμφανίζεται με αυτές τις μεθόδους παρέχει μια καλή υποστήριξη για την ένδειξη του πότε μια λειτουργία εμποδίζεται από μια άλλη και δίνει στο χρήστη τον έλεγχο να επιλύσει αυτή τη διένεξη. Όπου αυτό είναι δυνατόν, οι μακρόχρονες λειτουργίες θα πρέπει να εκτελούνται με τη χρήση της IProgressService#busyCursorWhile:

   IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
   progressService.busyCursorWhile(new IRunnableWithProgress(){
         public void run(IProgressMonitor monitor) {
         //do non-UI work
      }
   });

Αυτή η μέθοδος αρχικά θα χρησιμοποιήσει έναν απασχολημένο δρομέα και θα τον αντικαταστήσει με ένα πλαίσιο διαλόγου προόδου εάν η λειτουργία διαρκέσει περισσότερο από ένα καθορισμένο χρονικό όριο. Το πλεονέκτημα αυτής της μεθόδου συγκριτικά με τη χρήση ενός πλαισίου προόδου είναι ότι το πλαίσιο διαλόγου δεν θα εμφανιστεί εάν η λειτουργία είναι μικρής διάρκειας. Εάν η λειτουργία σας πρέπει να ενημερώσει το περιβάλλον χρήστη, μπορείτε να χρησιμοποιήσετε τη μέθοδο Display.asyncExec ή την Display.syncExec για να εκτελέσετε τον κώδικα ο οποίος τροποποιεί το περιβάλλον χρήστη.

Εάν μια λειτουργία πρέπει να εκτελεστεί στο σύνολό της στο νήμα του περιβάλλοντος χρήστη, τότε θα πρέπει να χρησιμοποιηθεί η IProgressService#runInUI. Αυτή η μέθοδος θα εμφανίσει επίσης ένα πλαίσιο διαλόγου εάν η λειτουργία εμποδιστεί και θα παραχωρήσει τον έλεγχο στο χρήστη.

   progressService.runInUI(
      PlatformUI.getWorkbench().getProgressService(),
      new IRunnableWithProgress() {
         public void run(IProgressMonitor monitor) {
            //do UI work
         }
      },
      Platform.getWorkspace().getRoot());

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

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

   IProgressService service = PlatformUI.getWorkbench().getProgressService();
   ImageDescriptor newImage = IDEInternalWorkbenchImages.getImageDescriptor(
      IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_MANUAL_BUILD);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_AUTO_BUILD);

Εμφάνιση ενός απασχολημένου τμήματος

Η διεπαφή IWorkbenchSiteProgressService περιλαμβάνει το API τον προγραμματισμό εργασιών, οι οποίες αλλάζουν την εμφάνιση ενός τμήματος του πάγκου εργασίας κατά την εκτέλεση της εργασίας. Εάν η πρόσθετη λειτουργία σας εκτελεί λειτουργίες στο παρασκήνιο οι οποίες επηρεάζουν την κατάσταση ενός τμήματος, μπορείτε να προγραμματίσετε την εργασία μέσω του τμήματος και ο χρήστης θα λάβει πρόσθετες πληροφορίες ότι το τμήμα είναι απασχολημένο. Ακολουθεί ένα παράδειγμα:

   IWorkbenchSiteProgressService siteService =
      (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
   siteService.schedule(job, 0 /* now */, true /* use the half-busy cursor in the part */);

Ιδιότητες προόδου για εργασίες

Ο πάγκος εργασίας ορίζει ιδιότητες σχετικές με την πρόοδο για εργασίες στην IProgressConstants. Αυτές μπορούν να χρησιμοποιηθούν για τον έλεγχο του τρόπου με τον οποίο μια εργασία εμφανίζεται στην προβολή προόδου. Μπορούν να χρησιμοποιηθούν ώστε η προβολή προόδου να διατηρήσει (IProgressConstants#KEEP_PROPERTY) την εργασία σας στην προβολή αφού αυτή ολοκληρωθεί ή να διατηρεί μόνο μια εργασία (IProgressConstants#KEEPONE_PROPERTY) κάθε φορά στην προβολή. Μπορείτε επίσης να συσχετίσετε μια ενέργεια (IProgressConstants#ACTION_PROPERTY) με μια εργασία. Όταν μια εργασία διαθέτει μια συσχετισμένη ενέργεια, η προβολή προόδου εμφανίζει μια υπερδιασύνδεση, ώστε ο χρήστης να μπορεί να εκτελέσει την ενέργεια. Μπορείτε επίσης να ανακαλύψετε εάν μια εργασία χρήστη εμφανίζεται τη δεδομένη στιγμή σε ένα πλαίσιο διαλόγου προόδου (IProgressConstants#PROPERTY_IN_DIALOG). Παρέχεται μια υπόδειξη κάτω δεξιά στη γραμμή κατάστασης όταν διατίθεται μια ενέργεια. Το ακόλουθο παράδειγμα χρησιμοποιεί αυτές τις ιδιότητες:

   Job job = new Job("Do Work") {
         public IStatus run(IProgressMonitor monitor) {
         // do some work.  
         // Keep the finished job in the progress view only if it is not running in the progress dialog
         Boolean inDialog = (Boolean)getProperty(IProgressConstants.PROPERTY_IN_DIALOG);
         if(!inDialog.booleanValue())
            setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
      }
   };
   job.setProperty(IProgressConstants.ICON_PROPERTY, Plugin.getImageDescriptor(WORK_IMAGE));
   IAction gotoAction = new Action("Results") {
      public void run() {
         // show the results
      }
   };
   job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
   job.setUser(true);
   job.schedule();

Εργασίες πάγκου εργασίας

Όπου αυτό είναι δυνατόν, οι μακρόχρονες λειτουργίες θα πρέπει να εκτελούνται εκτός του νήματος περιβάλλοντος χρήστη. Ωστόσο, αυτό δεν μπορεί να αποφευχθεί πάντα όταν ο σκοπός της λειτουργίας είναι η ενημέρωση του περιβάλλοντος χρήστη. Η ενότητα Θέματα νημάτωσης SWT εξηγεί τον τρόπο επίτευξης αυτού με τη χρήση της επιλογής SWT Εμφάνιση. Ο πάγκος εργασίας ορίζει μια ειδική εργασία , την UIJob, τις οποίας οι μέθοδοι εκτέλεσης εκτελούνται εντός μιας SWT asyncExec. Οι υποκλάσεις της UIJob θα πρέπει να υλοποιούν τη μέθοδο runInUIThread αντί της μεθόδου run.

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