2017-09-25 5 views
1

おそらくばかげた質問ですが、Roslynワークスペースに同時に信頼できる変更を適用する方法はありますか?そうでなければ、それが正しい順序で確実に行われるようにするためのベストプラクティスは何ですか?Roslynワークスペースを変更する同時性? Visual Studioはどのようにそれをしますか?

例:あなたはワークスペースにロードされたいくつかの解決策があるとし、ソリューションに新しいプロジェクトを追加します基本的な機能を持っている:

private Workspace _workspace; 

// This is not thread-safe, right? 
void AddProject() 
{ 
    var project = _workspace.CurrentSolution.AddProject(/* ... */); 
    _workspace.TryApplyChanges(project.Solution); 
} 

最初の質問:間違ったなら、私を修正して、私はAddProjectを考えますスレッドセーフではないでしょうか?

たとえば、新しいプロジェクトに同時に追加したいとします。つまり、AddProject()を同時に2回呼び出します。

競合状態があり、両方のプロジェクトを追加して終了する可能性があります(コールのいずれかがTryApplyChangesを完了してから_workspace.CurrentSolutionに到達する前に完了した場合)どちらかがTryApplyChangesを実行する前に_workapce.CurrentSolutionにコールが到達しました)。

第2の質問:私の理解が正しい場合、これらの並行性の問題を避けるための最善の方法はありますか?私は唯一の実際の方法は、各修正を順次スケジュール/実行することだと思いますよね?

たとえば、Visual Studioはこれをどのように行いますか。ディスパッチャーでのみ行われますか?

ありがとうございます。

+0

[OnProjectAdd](http://source.roslyn.codeplex.com/#Microsoft.CodeAnalysis.Workspaces/Workspace/Workspace.cs,9ef42d309f40029e)の実装を確認できます。それは 'SemaphoreSlim'を使用していますので、スレッドセーフです。派生したすべてのワークスペースは、私が知っているようにそれを呼び出します。 –

+0

ありがとうございます - 変更を適用するとソリューションのWorkspaceVersionが増加すると思いますが、これはこれらが一致しなくても次のアップデートが失敗することを意味します – Bogey

答えて

2

基本的なコードはスレッドセーフですが、使用方法はありません。

TryApplyChanges()解決策がその間に変更された場合はfalseを返します。その場合は、変更をもう一度試す必要があります(新しいCurrentSolutionから開始)。

基本的には、これは比較交換ループと呼ばれる

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

記述する必要があります。詳細はmy blogを参照してください。

+0

ありがとうございます。もしこれが一般的な慣行であるならば、あなたは何も知りません(VSやその他の主要なRoslynベースのソフトウェアがそれを扱うと言うことができます)?例えば。どんな状況下でもTryApplyChangesがいつも一定の修正に失敗して、あなたを無限ループにしてしまうのではないかと疑問に思っているのですか? – Bogey

+1

@Bogey:いいえ。解が一致しない場合はfalseを返すだけです。 http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Workspace/Workspace.cs,1109 – SLaks

関連する問題