批次資源變更

當您需要修改工作區中的資源時,請注意其他的外掛程式可能使用相同的資源。資源 API 提供健全機制來使外掛程式可以知道工作區中的變更,並確保多個外掛程式不會同時修改相同的資源。如果可能,您的外掛程式對工作區的修改應該是在工作區 Runnable 內的批次工作單元。這些 Runnable 能夠降低因變更而產生的變更通知數量。它們也可允許您宣告要修改工作區的哪一個部分,使得其他外掛程式能夠鎖定而不變更工作區的相同部分。

IWorkspaceRunnable 協定相當簡單。工作區 Runnable 看起來就像是長時間執行的作業或平台工作。實際的工作是在 run 方法內完成,並且會將進度報告給提供的 IProgressMonitor。操作工作區的程式碼是在 run 方法內執行。

IWorkspaceRunnable myRunnable = 
	new IWorkspaceRunnable() {
		public void run(IProgressMonitor monitor) throws CoreException {
			//在此執行實際工作
			...
		}
}

當即將要執行程式碼時,您的外掛程式會告訴工作區代表執行程式碼。這種方法,工作區可以產生任何必要的變更事件並確保不會有兩個外掛程式同時修改相同的資源。 (即使您的外掛程式未使用背景工作和並行組織架構來修改工作區,其他的外掛程式也可能這樣做。)

排程規則和鎖定

IWorkspace 協定是用來執行工作區 Runnable。偏好的技術是使用長形式的 run 方法,提供排程規則及指定如何廣播資源變更事件。

當執行工作區 Runnable 時指定排程規則,可允許工作區判斷資源變更是否會與其他執行緒發生的工作區變更發生衝突。(請參閱排程規則以取得排程規則和 ISchedulingRule 協定的概觀。) 幸運地,IResource 協定包括 ISchedulingRule 的協定, 這表示資源可以經常作為本身的排程規則。

混淆了嗎?程式碼可以幫助釐清這一點。假設您的外掛程式準備要修改特定專案中的一組資源。可以使用專案本身作為排程規則來進行變更。下列片段執行我們稍早建立的工作區 Runnable︰

    IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);

Runnable 會傳入工作區,隨後是程式碼操作的專案。這會告訴工作區 Runnable 中的所有變更都限制在 myProject 中。其他執行緒變更 myProject 的要求都會被暫停執行,直到這個 Runnable 完成為止。同樣地,如果有其他的執行緒已經在修改 myProject,這個呼叫也將會暫停執行。藉著指定 Runnable 將會修改資源樹狀結構的哪一部分,可允許其他執行緒繼續修改工作區的其他部分。確定您的資源規則符合要在 Runnable 內完成的工作是非常重要的。試圖存取排程規則範圍之外的資源將會觸發異常狀況。

run 方法的第三個參數指定是否有任何週期性的資源變更事件應該在這個呼叫的範圍期間廣播。使用 IWorkspace.AVOID_UPDATE 告訴平台當 Runnable 正在執行時抑制任何的資源變更事件,並在變更的結尾時廣播一個事件。在這個呼叫期間,在 Runnable 中建立的任何其他 Runnable 將被視為母項批次作業的一部分。在這些 Runnable 中所做的資源變更會出現在母項的資源變更通知中。

資源規則 Factory

在上例中,我們假設在 Runnable 內的程式碼僅修改特定專案中的資源。這使得它非常容易指定排程規則給 Runnable。實際上,要計算特定的變更會影響工作區的哪些部分會困難得多。比如說,從某個專案移動資源到另一個專案會影響這兩個專案。IResourceRuleFactory 可以用來幫助計算適用某些資源變更種類的資源規則。您可以從工作區本身取得資源規則 Factory。

    IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceRuleFactory ruleFactory = workspace.getRuleFactory();

Factory 可以提供適用多種作業的規則。如果您的 Runnable 是從某個位置移動資源到另一個位置,可以取得適用這項作業的規則︰

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);

請參閱 IResourceRuleFactory 的 Javadoc 以取得可用規則的清單。資源外掛程式本身使用這些規則來實作大部分的資源作業。瀏覽參照這些規則方法的程式碼有助於示範其實際使用方式。

使用 MultiRule 可以結合多重規則。

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource);
workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);

忽略規則

IWorkspace 中也有短形式的 run 方法。這是為了舊版相容性而保留。短形式不包括規則或更新旗標。

workspace.run(myRunnable, null);

效用與呼叫下列相同

workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);

指定工作區根作為排程規則將會鎖定整個工作區,直到 Runnable 完成為止。這是執行工作區最保守的更新方法,但是對於重視並行性的其他外掛程式而言並不友善。