修改Roslyn工作区的并发性? Visual Studio如何做到这一点?

时间:2017-09-25 21:24:59

标签: c# visual-studio roslyn

可能是一个愚蠢的问题,但是:有没有办法可靠地同时应用对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上完成?

由于

1 个答案:

答案 0 :(得分:2)

底层代码是线程安全的,但您的用法不是。

如果在此期间解决方案发生变化,

TryApplyChanges()将返回false。如果发生这种情况,您需要再次尝试更改(从新的CurrentSolution开始)。

基本上,你需要写

Solution changed;
do {
  changed = _workspace.CurrentSolution....();
} while (!_workspace.TryApplyChanges(changed);

这称为比较和交换循环;有关详细信息,请参阅my blog