In een eerder onderwerp is al uitgelegd dat het JFace-gebruikersinterfaceframework de voortgang van taken in een dialoogvenster kan afbeelden. (Raadpleeg Langdurige bewerkingen voor meer informatie.) In Gemeenschappelijke infrastructuur is de runtime-ondersteuning van het platform voor gemeenschappelijk gebruik en langdurige bewerkingen aan bod gekomen. In dit onderwerp komt u te weten hoe deze infrastructuur door de platformgebruikersinterface uitgebreid wordt met het pakket org.eclipse.ui.progress. Dit pakket levert de gebruikersinterface voor het afbeelden van de voortgang van taken in de workbench en definieert aanvullende ondersteuning voor taken die in de gebruikersinterface-thread worden uitgevoerd.
Eerst komen de verschillende soorten achtergrondbewerkingen aan bod en wordt uitgelegd hoe deze kunnen worden uitgevoerd en worden afgebeeld in de gebruikersinterface van de workbench:
Gebruikerstaken zijn door de gebruiker zelf gestart. De voortgang van dergelijke taken wordt door de workbench automatisch afgebeeld in een modaal dialoogvenster met een knop. De gebruiker kan vervolgens zelf bepalen of hij de bewerking op de achtergrond wil uitvoeren, zodat hij kan doorgaan met zijn werk. Er is een globale voorkeursinstelling waarmee kan worden aangegeven of gebruikerstaken altijd op de achtergrond moeten worden uitgevoerd. Gebruikerstaken herkent u in de taken-API aan Job#setUser. Voorbeelden van gebruikerstaken zijn het bouwen en reserveren van een project, het synchroniseren van het project met de repository, het exporteren van een plugin en het uitvoeren van zoekopdrachten.
Automatisch gestarte taken zijn niet door de gebruiker zelf gestart, maar zijn wel van belang voor. Dergelijke taken worden wel in de voortgangsview en op de statusbalk afgebeeld, maar niet in een modaal voortgangsdialoogvenster. Voorbeelden van automatische bewerkingen zijn automatisch bouwen en geplande synchronisatie.
Systeemtaken worden niet door de gebruiker gestart en kunnen als interne platformprocessen worden beschouwd. Dergelijke taken worden gemaakt door het systeemkenmerk in te stellen met Job#setSystem. Voorbeelden van systeemtaken zijn het invullen van widgets of het berekenen van decoraties en annotaties van views.
In een omgeving waar meerdere processen gelijktijdig kunnen worden uitgevoerd, is het volgende van belang voor de gebruiker:
Een aanwijzing dat een langdurige bewerking is gestart.
Gebruikerstaken worden afgebeeld in een voortgangsdialoogvenster. Automatisch gestarte taken worden op de statusbalk en in de voortgangsview afgebeeld. Taken die van toepassing zijn op onderdelen, moet u plannen of registreren met de onderdelen. De workbench kan u dan informeren als bewerkingen worden uitgevoerd die onderdelen beïnvloeden.
Een aanwijzing dat een bewerking is beëindigd.
Zodra het dialoogvenster wordt gesloten, is een gebruikerstaak beëindigd. Voor taken die niet door de gebruiker zelf worden gestart, gelden andere aanwijzingsregels. Als de taak is gepland of geregistreerd met een onderdeel, wordt de voortgangsaanwijzing afgebeeld zodra de taak is voltooid. Indien tijdens het uitvoeren van een taak een fout optreedt, wordt rechtsonder op de statusbalk een foutaanduiding afgebeeld.
Een aanwijzing van interessante nieuwe resultaten of nieuwe gegevens, zonder daarbij de focus weg te kapen.
Voor een gebruikerstaak worden de resultaten direct na het voltooien van de taak afgebeeld. Voor andere taken is het raadzaam een andere techniek toe te passen dan een dialoogvenster, zodat de gebruiker ongestoord kan doorwerken. Bij het starten van een taak kan bijvoorbeeld een view worden geopend waarin de resultaten worden afgebeeld zonder de gebruiker lastig te vallen. Bovendien kunnen taakeigenschappen worden ingesteld voor een taak om aan te geven dat deze in de voortgangsview moet blijven en een actie bevat voor het afbeelden van de resultaten. Er wordt dan rechtsonder op de statusbalk een waarschuwingsaanduiding afgebeeld wanneer resultaten zijn verzameld.
Het gevoel hebben te weten welke processen er worden uitgevoerd en over de mogelijkheid beschikken op de achtergrond uitgevoerde bewerkingen te controleren en te annuleren.
Gebruikerstaken kunnen eenvoudig worden geannuleerd en geven een sterke aanwijzing van blokkerende of gedeelde bewerkingen via het gegevenstabblad van het voortgangsdialoogvenster. Merk op dat het uitgebreide voortgangsdialoogvenster met het gegevensgebied alleen wordt afgebeeld wanneer plugins gebruik maken van IProgressService#busyCursorWhile of IProgressService#runInUI. Bovendien kunt u in de voortgangsview zien welke actieve taken worden uitgevoerd.
Een consistente voortgangsrapportage door alle geïnstalleerde plugins.
Het voordeel van de voortgangsservice-API is het kunnen leveren van een consistente voortgangsinformatievoorziening.
De voortgangsservice van de workbench (IProgressService) is de primaire interface voor voortgangsondersteuning door de workbench. U kunt de service ophalen uit de workbench en vervolgens gebruiken om de voortgang af te beelden van zowel achtergrondbewerkingen als bewerkingen die in de gebruikersinterface-thread worden uitgevoerd. Deze klasse fungeert voornamelijk als centraal punt voor uitgevoerde bewerkingen, zodat ontwikkelaars van plugins niet steeds hoeven na te denken over een manier voor het afbeelden van voortgang. Bovendien kan het voortgangsdialoogvenster worden ingezet om conflicten tussen bewerkingen aan te duiden, zodat de gebruiker zelf kan bepalen hoe het probleem moet worden opgelost. Waar mogelijk moeten langdurige bewerkingen worden uitgevoerd met IProgressService#busyCursorWhile:
IProgressService progressService = PlatformUI.getWorkbench().getProgressService(); progressService.busyCursorWhile(new IRunnableWithProgress(){ public void run(IProgressMonitor monitor) { // non-gebruikersinterface-instructies } });
Met deze methode wordt de cursor aanvankelijk gewijzigd in "bezet" en verschijnt een voortgangsdialoogvenster als de uitvoering van de taak langer duurt dan een bepaalde tijddrempelwarde. Het voordeel van deze methode is dat het voortgangsdialoogvenster niet wordt afgebeeld voor kortstondige bewerkingen. Als de bewerking de gebruikersinterface moet bijwerken, kunt u altijd gebruik maken van Display.asyncExec of Display.syncExec voor het uitvoeren van de code waarmee de gebruikersinterface wordt gewijzigd.
Moet een bewerking volledig in de gebruikersinterface-thread worden uitgevoerd, dan moet u IProgressService#runInUI gebruiken. Met deze methode wordt ook een dialoogvenster afgebeeld als de bewerking wordt geblokkeerd en kan de gebruiker actie ondernemen.
progressService.runInUI( PlatformUI.getWorkbench().getProgressService(), new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { // gebruikersinterface-instructies } }, Platform.getWorkspace().getRoot());
De derde parameter mag null blijven of moet anders een planregel voor de bewerking zijn. In dit voorbeeld wordt de directory van het werkgebied opgegeven, waardoor het werkgebied niet reageert tijdens het uitvoeren van de gebruikersinterfacebewerking.
U kunt ook een pictogram van de taakcategorie registreren met de voortgangsservice, zodat het pictogram wordt afgebeeld naast de uitgevoerde taak in de voortgangsview. In het onderstaande voorbeeld ziet u hoe de taakcategorie voor automatisch bouwen aan een pictogram wordt gekoppeld:
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 bevat API voor het plannen van taken waarmee de presentatie van workbenchonderdelen wordt gewijzigd tijdens de taakuitvoering. Als met uw plugin bewerkingen op de achtergrond worden uitgevoerd die van invloed zijn op de status van een onderdeel, kunt u de taak plannen via het onderdeel. De gebruiker wordt dan geïnformeerd wanneer het onderdeel bezet is. Hier volgt een voorbeeld:
IWorkbenchSiteProgressService siteService = (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class); siteService.schedule(job, 0 /* nu */, true /* cursor met pijl en zandloper */);
In de workbench worden voortgangseigenschappen voor taken gedefinieerd in IProgressConstants. Deze eigenschappen komen van pas bij het instellen van de presentatie van een taak in de voortgangsview. U kunt in de eigenschappen aangeven dat de taak niet uit de view moet worden gewist nadat deze is voltooid (IProgressConstants#KEEP_PROPERTY) of dat slechts één view per keer mag worden afgebeeld in de view (IProgressConstants#KEEPONE_PROPERTY). U kunt ook een actie aan een taak koppelen (IProgressConstants#ACTION_PROPERTY). Wanneer een actie aan een taak is gekoppeld, wordt in de voortgangsview een hyperlink afgebeeld waarmee de gebruiker de actie kan uitvoeren. U kunt ook achterhalen of een gebruikerstaak wordt afgebeeld in een voortgangsdialoogvenster (IProgressConstants#PROPERTY_IN_DIALOG). Wanneer er een actie beschikbaar is, wordt rechtsonder op de statusbalk een aanduiding afgebeeld. In het volgende voorbeeld worden deze eigenschappen gebruikt:
Job job = new Job("Instructies uitvoeren") { public IStatus run(IProgressMonitor monitor) { // Enkele instructies uitvoeren. // Houd de voltooide taak alleen in de voortgangsview als het voortgangsdialoogvenster niet wordt afgebeeld. 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("Resultaten") { public void run() { // De resultaten afbeelden. } }; job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction); job.setUser(true); job.schedule();
Waar mogelijk moeten langdurige bewerkingen buiten de gebruikersinterface-thread om worden uitgevoerd. Wanneer de gebruikersinterface moet worden bijgewerkt, is dit echter niet te voorkomen. In Problemen met threads kunt u zien hoe u dit in zijn werk gaat met SWT Display. Door de workbench wordt een speciale taak gedefinieerd, UIJob, waarvan de methoden worden uitgevoerd in een SWT asyncExec. Voor subklassen van UIJob moet de methode runInUIThread worden geïmplementeerd in plaats van de methode run.
WorkbenchJob is een uitbreiding van UIJob, zodat de taak alleen kan worden gepland of uitgevoerd wanneer de workbench actief is. U moet altijd voorkomen dat de gebruikersinterface-thread zwaar wordt belast, omdat de gebruikersinterface niet wordt vernieuwd tijdens de uitvoering van de gebruikersinterfacetaak.