2017-09-25 1 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()를 동시에 두 번 호출합니다.

필자가 알고있는 것은 경쟁 조건이 있기 때문에 두 프로젝트가 모두 추가되었다는 것입니다 (다른 호출이 _workspace.CurrentSolution에 도달하기 전에 호출 중 하나가 TryApplyChanges를 완료하는 경우) 또는 추가 된 프로젝트 중 하나만 TryApplyChanges를 실행하기 전에 호출이 _workapce.CurrentSolution에 도달했습니다.

두 번째 질문 : 제 이해가 정확하다면이 동시성 문제를 피할 수있는 가장 좋은 방법이 있습니까? 유일하게 실제적인 방법은 각 수정 작업을 일정에 따라/실행하는 것입니다.

예를 들어 Visual Studio는 어떻게됩니까? 작업 영역을 수정합니다. 예 : Dispatcher에서만 완료 되었습니까?

감사합니다.

+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 : No; 솔루션이 일치하지 않는 경우에만 false를 반환합니다. http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Workspace/Workspace.cs,1109 – SLaks

관련 문제