可能是一个愚蠢的问题,但是:有没有办法可靠地同时应用对Roslyn工作区的更改?如果没有,确保按正确顺序完成的最佳做法是什么?
示例:假设您已将某个解决方案加载到工作区中,并且具有将向解决方案添加新项目的基本功能:
private Workspace _workspace;
// This is not thread-safe, right?
void AddProject()
{
var project = _workspace.CurrentSolution.AddProject(/* ... */);
_workspace.TryApplyChanges(project.Solution);
}
第一个问题:如果错误,请纠正我,但我认为AddProject不是线程安全的,这是正确的吗?
例如,假设您要同时添加到新项目中。所以你同时调用AddProject()两次。
我的理解是存在竞争条件,您最终可能会添加两个项目(如果其中一个调用在另一个调用到达_workspace.CurrentSolution之前完成TryApplyChanges),或者只添加了其中一个项目(如果两个调用都有)在执行TryApplyChanges之前已经达到_worksapce.CurrentSolution。
第二个问题:如果我的理解是正确的,那么有没有最好的方法来避免这些并发问题?我想唯一真正的方法是连续安排/执行每个修改,对吗?
例如,Visual Studio如何执行此操作..是否对工作区进行了修改,例如只能在Dispatcher上完成?
由于
答案 0 :(得分:2)
底层代码是线程安全的,但您的用法不是。
如果在此期间解决方案发生变化, TryApplyChanges()
将返回false。如果发生这种情况,您需要再次尝试更改(从新的CurrentSolution
开始)。
基本上,你需要写
Solution changed;
do {
changed = _workspace.CurrentSolution....();
} while (!_workspace.TryApplyChanges(changed);
这称为比较和交换循环;有关详细信息,请参阅my blog。