Munkaterület-konkurencia támogatás

Láthattuk, hogy a JFace UI keretrendszer alap támogatást biztosít a feladat-előrehaladás párbeszédablakban megjelenítéséhez (részletes információkat a Hosszan futó műveletek rész tartalmaz). A Konkurencia-infrastruktúrában áttekintettük a konkurens és hosszan futó műveletek platform futási támogatását. Most megtekintjük, hogy a platform UI az org.eclipse.ui.progress csomagban hogyan javítja ezt az infrastruktúrát. Ez a csomag biztosítja a felhasználói felületet a feladat-előrehaladás munkaterületen megjelenítéséhez, és további támogatást ad meg az UI szálban futó feladatokhoz.

Először tekintsük meg azon háttérműveletek különböző típusait és a munkaterület felhasználói felületén megjelenésük módját, amelyek futhatnak:


Adva van egy környezet, amelyben számos dolog történhet egyszerre, amikor a felhasználónak az alábbiakra van szüksége:

Előrehaladás szolgáltatás

A munkaterület előrehaladás szolgáltatás (IProgressService) az elsődleges felület a munkaterület előrehaladás támogatásához. Ez a munkaterületről kérhető le, majd megjeleníti az előrehaladást az UI szálban futó műveletekhez és háttérműveletekhez. Az osztály fő célja, hogy a futó műveletekhez mindent egy helyen biztosítson, ezáltal a bedolgozófejlesztőknek nem kell eldönteniük, hogy milyen mechanizmusokat kell használni az előrehaladás megjelenítéséhez egy adott helyzetben. Másik előny, hogy ezen metódusokkal megjelenő előrehaladás párbeszédablak támogatja annak jelzését, hogy a műveletet egy másik blokkolja és lehetővé teszi a felhasználó számára, hogy vezérelje a konfliktus feloldását. Ahol lehetséges, a hosszan futó feladatokat az IProgressService#busyCursorWhile segítségével kell futtatni:

   IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
   progressService.busyCursorWhile(new IRunnableWithProgress(){
         public void run(IProgressMonitor monitor) {
         //nem UI feladat végzése
      }
   });

Ez a metódus kezdetben egy foglalt kurzort jelenít meg, és ha a művelet a megadott küszöbértéknél tovább tart, akkor lecseréli ezt egy előrehaladás párbeszédablakra. Ezen metódus előnye az előrehaladás párbeszédablakkal szemben, hogyha a művelet rövid ideig fut, akkor az előrehaladás párbeszédablak nem jelenik meg. Ha a műveletnek frissítenie kell a felhasználói felületet, akkor mindig használhat egy Display.asyncExec vagy Display.syncExec elemet a kód futtatásához, amely módosítja a felhasználói felületet.

Ha egy műveletet teljes egészében kell futtatni a felhasználói felületen, akkor az IProgressService#runInUI elemet kell használni. Ez a metódus megjelenít egy előrehaladás párbeszédablakot is, ha a művelet blokkolva van, és biztosítja a vezérlést a felhasználó számára.

   progressService.runInUI(
      PlatformUI.getWorkbench().getProgressService(),
      new IRunnableWithProgress() {
         public void run(IProgressMonitor monitor) {
            //UI feladat végzése
         }
      },
      Platform.getWorkspace().getRoot());

A harmadik paraméter lehet null, vagy a művelet ütemezési szabálya. Ebben a példában megadjuk a munkaterület-gyökeret, amely zárolja a munkaterületet, amíg ez az UI feladat fut.

Az előrehaladás szolgáltatással a feladatcsaládhoz egy ikon is regisztrálható, így az előrehaladás nézet a futó feladat mellett megjelenítheti az ikont. Az alábbiakban látható egy példa arra, hogy a feladatcsalád automatikus összeépítése hogyan társítható ezzel az ikonnal:

   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);

Megjeleníti, hogy a rész foglalt

Az IWorkbenchSiteProgressService alkalmazás programozási felületet tartalmaz a feladatok ütemezéséhez, amely módosítja a munkaterületrész megjelenítését, miközben a feladat fut. Ha a bedolgozó háttérműveleteket futtat, amelyek hatással vannak a rész állapotára, akkor a feladat ütemezhető a részen keresztül, és a felhasználó visszajelzést kap arról, hogy a rész foglalt. Az alábbiakban látható egy példa:

   IWorkbenchSiteProgressService siteService =
      (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
   siteService.schedule(job, 0 /* most */, true /* fel használt kurzort használ */);

Folyamat-tulajdonságok a feladatokhoz

A munkaterület az előrehaladással kapcsolatos tulajdonságokat határoz meg a feladatok számára az IProgressConstants felületben. Ezek segítségével a feladat megjelenése vezérelhető az előrehaladás nézetben. Ezek előírhatják az előrehaladás nézetnek, hogy (IProgressConstants#KEEP_PROPERTY) a feladat befejezés után a nézetben maradjon, vagy hogy csak egy (IProgressConstants#KEEPONE_PROPERTY) feladat maradjon egyszerre a nézetben. A feladathoz társítható egy tevékenység (IProgressConstants#ACTION_PROPERTY). Ha a feladat rendelkezik egy társított tevékenységgel, akkor az előrehaladás nézet megjelenít egy hivatkozást, így a felhasználó futtathatja a tevékenységet. Azt is észreveheti, hogy a felhasználó aktuálisan megjelenik-e az előrehaladás párbeszédablakban (IProgressConstants#PROPERTY_IN_DIALOG). Egy tipp jelenik meg az állapotsor jobb alsó részében, amikor az állapotsor rendelkezésre áll. Az alábbi példa ezen tulajdonságokat használja:

   Job job = new Job("Do Work") {
      public IStatus run(IProgressMonitor monitor) {
         // feladatok elvégzése.  
         // csak a befejezett feladat megtartása az előrehaladás nézetben, ha nem fut az előrehaladás párbeszédablakban
         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() {
         // megjeleníti az eredményeket
      }
   };
   job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
   job.setUser(true);
   job.schedule();

Munkaterület-feladatok

Ahol lehetséges, ott a hosszútávú műveleteket az UI szálon kívül kell végrehajtani. Ez nem mindig lehetséges, amikor a művelet célja az UI frissítése. SWT szálkezelési problémák bemutatják, hogy ez hogyan hajtható végre az SWT Display segítségével. A munkaterület egy speciális feladatot - UIJob - ad meg, amelynek run metódusa egy SWT asyncExec elemen belül fut. Az UIJob alosztályainak a run metódus helyett a runInUIThread metódust kell megvalósítaniuk.

WorkbenchJob kiterjeszti az UIJob feladatot, így a feladat csak akkor ütemezhető vagy futtatható, amikor a munkaterület fut. Ahogy mindig, most is el kell kerülni a túlzott munkát az UI szálban, mivel az UI nem kerül frissítésre az UI feladat során.