访问 EclipsePreferences 的线程安全方式(项目)
Thread-Safe way to access EclipsePreferences (Project)
我目前正在开发一个 Eclipse-RCP 应用程序,它通过 ProjectScope 使用 EclipsePreference 机制存储每个项目的首选项。起初这似乎工作得很好,但我们 运行 在多线程场景中(读取)访问这些首选项时遇到了麻烦,同时对工作区进行了更改。似乎特别有问题的是在通过异步用户操作(右键单击项目 -> 删除项目)删除项目时访问这样的首选项节点 (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文档中真正找到上述问题的答案。
通常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。
我目前正在开发一个 Eclipse-RCP 应用程序,它通过 ProjectScope 使用 EclipsePreference 机制存储每个项目的首选项。起初这似乎工作得很好,但我们 运行 在多线程场景中(读取)访问这些首选项时遇到了麻烦,同时对工作区进行了更改。似乎特别有问题的是在通过异步用户操作(右键单击项目 -> 删除项目)删除项目时访问这样的首选项节点 (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文档中真正找到上述问题的答案。
通常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。