我目前正在开发一个Eclipse-RCP应用程序,它通过 ProjectScope 使用 EclipsePreference 机制存储每个项目的首选项。起初这看起来效果很好,但是在多线程场景中(读取)访问这些首选项时,我们遇到了麻烦,同时对工作区进行了更改。看起来特别有问题的是在异步用户操作(右键单击Project - > Delete Project)删除项目时访问此类首选项节点(ProjectScope.getNode()
)。在这种情况下,我们得到了很好的混合
org.osgi.service.prefs.BackingStoreException
java.io.FileNotFoundException
org.eclipse.core.runtime.CoreException
基本上他们都抱怨基础文件不再存在。
使用IProject.exists()
或isAccessible()
之类的检查进行修复的初步尝试,甚至可以检查实际.prefs文件的存在,这与预期一样无效:他们只会减少异常,但不会真正阻止它们。
所以我的问题是:您如何安全地访问ProjectScope.getNode()
之类的内容?您是否需要将每次阅读放到WorkspaceJob
或是否有其他一些聪明的方法可以防止上述问题,例如将读取权限放入Display.asyncExec()
?
虽然我尝试过,但我并没有在Eclipse文档中找到上述问题的答案。
答案 0 :(得分:1)
通常scheduling rules用于同时访问工作区中的资源。
我从未使用ProjectScope
ed偏好设置,但如果它们存储在项目或其元数据中,则调度规则应该有助于协调访问。如果您在作业中运行首选项访问代码,则应设置适当的调度规则:
例如:
IProject project = getProjectForPreferences( projectPreferences );
ISchedulingRule rule = project.getWorkspace().getRuleFactory().modifyRule( project );
Job job = new Job( "Access Project Preferences" ) {
@Override
protected IStatus run( IProgressMonitor monitor ) {
if( project.exists() ) {
// read or write project preferences
}
return Status.OK_STATUS;
}
};
job.setRule( rule );
job.schedule();
代码获取修改项目的规则,并且只有在没有其他具有冲突规则的作业运行时,才能保证作业运行。
如果您的代码未在作业中运行,您还可以手动获取IJobManager.beginRule()
和endRule()
的锁定。
例如:
ISchedulingRule rule = ...;
try {
jobManager.beginRule( rule, monitor );
if( project.exists() ) {
// read or write project preferences
}
} finally {
jobManager.endRule( rule );
}
看起来很尴尬,对beginRule
的调用必须在try块中,有关详细信息,请参阅JavaDoc。