Når du har brug for at ændre ressourcer i arbejdsområdet, er det vigtigt at være opmærksom på, at der kan være andre plugins, der arbejder med de samme ressourcer. Ressource-API'et stiller robuste mekanismer til rådighed, som løbende holder plugins orienteret om ændringer i arbejdsområdet, og som sikrer, at flere plugins ikke ændrer den samme ressource samtidigt. Når det er muligt, bør plugin-ændringer til arbejdsområdet udføres samlet i arbejdsenheder i en arbejdsområde-runnable. Disse runnables hjælper med at reducere mængden af ændringsmeddelelser, der skal genereres af ændringer. De giver dig også mulighed for at erklære, hvilke dele af arbejdsområdet der skal ændres, så andre plugins forhindres i at ændre samme del af arbejdsområdet.
Protokollen for IWorkspaceRunnable er ret enkel. En workspace-runnable ligner en langvarig funktion eller et langvarigt platformjob. Det egentlige arbejde finder sted i en run-metode, og status rapporteres til den leverede IProgressMonitor. Kode, der arbejder med arbejdsområdet, udføres inde i run-metoden.
IWorkspaceRunnable myRunnable = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { //udfører det egentlige arbejde her ... } }
Når det er tid til at udføre koden, underretter plugin'en arbejdsområdet om at udføre koden for sig. På den måde kan arbejdsområdet generere eventuelle nødvendige ændringsaktiviteter og sikre, at der ikke er to plugins, som ændrer den samme ressource på samme tid. (Selvom din plugin ikke bruger baggrundsjob og samtidighedsrammen til at ændre arbejdsområdet, kan der være andre, der gør).
IWorkspace-protokollen bruges til at udføre en arbejdsområde-runnable. Den foretrukne teknik er at benytte den lange form af run-metoden, som leverer en planlægningsregel og angiver, hvordan ressourceændringsaktiviteter rundsendes.
Angivelse af en planlægningsregel, når en arbejdsområde-runnable udføres, giver arbejdsområdet mulighed for at afgøre, om ressourceændringerne vil være i konflikt med andre arbejdsområdeændringer, der finder sted i andre programdele. (I Planlægningsregler finder du en oversigt over planlægningsregler og protokollen ISchedulingRule.) Heldigvis indeholder protokollen IResource protokollen for ISchedulingRule, og det betyder, at en ressource ofte kan benyttes som en planlægningsregel for sig selv.
Det kan være en anelse forvirrende, men kode kan afklare det. Antag, at din plugin er ved at gøre sig klar til at ændre en række ressourcer i et bestemt projekt. Den kan bruge selve projektet som planlægningsregel for udførelsen af ændringerne. Følgende stykke kode udfører den arbejdsområde-runnable, vi oprettede tidligere:
IWorkspace arbejdsområde = ResourcesPlugin.getWorkspace(); workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);
Runnable overføres til arbejdsområdet efterfulgt at det projekt, som koden arbejder med. Det fortæller arbejdsområdet, at alle ændringerne i runnable er begrænset til myProject. Alle anmodninger fra andre programdele om at ændre myProject, blokeres, indtil denne runnable er færdig. På samme måde blokeres dette kald, hvis en anden programdel allerede er ved at ændre myProject. Ved at angive, hvilken del af ressourcetræstrukturen der skal ændres af runnable, er det muligt for andre programdele at ændre andre dele af arbejdsområdet. Det er vigtigt, at ressourcereglen matcher det arbejde, der udføres inde i runnable. Når en planlægningsregel, der ikke er NULL, anvendes, vil ethvert forsøg på at få adgang til en ressource uden for planlægningsreglens omfang udløse en undtagelse.
Der er to særlige planlægningsregler, det er vigtigt at overveje. For det første: Hvis du bruger en forekomst af IWorkspaceRoot som planlægningsregel, betyder det, at programdelen blokerer adgang til alle ressourcer i træstrukturen. Ingen anden programdel har tilladelse til at ændre arbejdsområdet, mens en programdel holder rodreglen. På samme vil en NULL-regel angive, at ingen ressourcer i træstrukturen blokeres af programdelen.Selvom en programdel med en NULL-regel frit kan ændre selve arbejdsområdet, forhindres andre programdele ikke i at foretage deres egne ændringer. Planlægningsreglerne IWorkspaceRoot og NULL ligger i hver sin ende af samtidighedsspektret. Med IWorkspaceRoot er der ingen samtidighed, og kun én programdel ad gangen kan ændre arbejdsområdet. Med en NULL-regel er der maksimal samtidighed, da alle programdele samtidigt kan ændre arbejdsområdet.
Den tredje parameter for run-metoden angiver, om periodiske ressourceændringsaktiviteter skal rundsendes inden for omfanget af dette kald. Ved hjælp af IWorkspace.AVOID_UPDATE informeres platformen om at undertrykke alle ressourceændringsaktiviteter, mens runnable udføres og om at rundsende én aktivitet, når ændringerne er udført. Under dette kald betragtes alle andre runnables, der er oprettet i denne runnable, som en del af den overordnede batchfunktion. Ressourceændringer, der er foretaget i disse runnables, vises i den overordnedes ressourceændringsunderretning.
I ovenstående eksempel antog vi, at koden inde i vores runnable kun ændrede ressourcer i et bestemt projekt. Det gjorde det meget let at angive en planlægningsregel for runnable. I praksis kan det være sværere at beregne, hvilke dele af arbejdsområdet der påvirkes af en bestemt ændring. Flytning af en ressource fra et projekt til et andet påvirker begge projekter. IResourceRuleFactory kan bruges til at hjælpe ved beregningen af en relevant ressourceregel for visse typer ressourceændringer. Du kan hente en ressourceregelfabrik for selve arbejdsområdet.
IWorkspace arbejdsområde = ResourcesPlugin.getWorkspace(); IResourceRuleFactory ruleFactory = workspace.getRuleFactory();
Fabrikken kan stille regler til rådighed, som er relevante for mange typer funktioner. Hvis runnable flytter en ressource fra en placering til en anden, kan den hente en regel, der er relevant for denne funktion:
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);
I javadoc for IResourceRuleFactory finder du en liste over de tilgængelige regler. Ressource-plugin'en bruger også disse regler til at implementere de fleste ressourcefunktioner. Ved at gennemgå den kode, der refererer til disse regelmetoder, kan du se, hvordan de bruges i praksis.
Flere regler kan kombineres vha. MultiRule.
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource); workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);
Den korte form af run-metoden i IWorkspace er også tilgængelig. Den bevares af hensyn til bagudrettet kompatibilitet. Den korte form indeholder ikke en regel eller et opdateringsflag.
workspace.run(myRunnable, null);
svarer til at kalde
workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);
Angivelse af arbejdsområderoden som planlægningsregel placerer en lås på hele arbejdsområdet, indtil runnable er færdig. Denne måde er den mest konservative måde at foretage en arbejdsområdeopdatering på, men den tager ikke hensyn til andre plugins, der lægger vægt på samtidighed.