以编程方式构建项目时,“此集合是只读”异常

时间:2013-11-25 00:05:24

标签: c# .net exception msbuild invalidoperationexception

我正在并行运行一些单元测试。每个单元测试都会调用一些触发SSDT数据库项目的MSBuild部署的代码:

void Deploy(string projectPath, string publishProfilePath, ILogger logger)
{
    var project = ProjectCollection.GlobalProjectCollection.LoadProject("projectPath);

    Projects.SetGlobalProperty("Configuration", "Debug");
    Projects.SetGlobalProperty("SqlPublishProfilePath", publishProfilePath);
    var targets = new[] { "Build", "Publish" };

    project.Build(targets, new[] { logger });
}

此方法的最后一行抛出InvalidOperationException,并显示以下消息:

  

此集合是只读的。

这是调用堆栈跟踪的相关部分:

   at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args)
   at Microsoft.Build.Collections.RetrievableEntryHashSet`1.AddEvenIfPresent(T value)
   at Microsoft.Build.Evaluation.Project.Data.AddTarget(ProjectTargetInstance target)
   at Microsoft.Build.Evaluation.Evaluator`4.ReadTargetElement(ProjectTargetElement targetElement, LinkedList`1 activeTargetsByEvaluationOrder, Dictionary`2 activeTargets)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate()
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext, ProjectInstance projectInstanceIfAnyForDebuggerOnly)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation)
   at Microsoft.Build.Evaluation.Project.CreateProjectInstance(ILoggingService loggingServiceForEvaluation, ProjectInstanceSettings settings)
   at Microsoft.Build.Evaluation.Project.Build(String[] targets, IEnumerable`1 loggers, IEnumerable`1 remoteLoggers)
   at Microsoft.Build.Evaluation.Project.Build(String[] targets, IEnumerable`1 loggers)

Build方法的文档似乎没有提到这一点。这段代码以前有用过。

1 个答案:

答案 0 :(得分:0)

我怀疑MSBuild以这种方式不是线程安全的。

当我使用lock阻止多次同时调用代码时,我的代码线程安全时不再出现问题:

void Deploy(string projectPath, string publishProfilePath, ILogger logger)
{
    lock (deployLock)
    {
        //Implementation
    }
}

object deployLock = new object();