roslyn: System.AggregateException with innerException "A task was cancelled" trying to add reference to certain projects of a solution

Version Used: Latest version 1.3.2

Steps to Reproduce:

  1. Load a sample standalone solution file that has some of our real production solution’s projects, enumerate each project trying to add a code coverage dll, most will add but a small few will fail with the exception.

I have a standalone that repro the issue. But I couldn’t share the actual solution file as it’s part of our production source code. I have copy the whole standalone repro code below for diagnosis.

Expected Behavior: TryApplyChanges call succeed for all projects

Actual Behavior: It will fail on a small subset of projects .

Repro code:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.MSBuild; using System.Reflection;

namespace ConsoleApplication4 { class Program { static void Main(string[] args) {

        string projName = args[0];
        MSBuildWorkspace workspace=null;
        try
        {
            workspace = MSBuildWorkspace.Create();
        }
        catch (Exception ex)
        {
            if (ex is System.Reflection.ReflectionTypeLoadException)
            {
                var typeLoadException = ex as ReflectionTypeLoadException;
                var loaderExceptions = typeLoadException.LoaderExceptions;
            }
        }
        // In this sample solution file that I try to load, it has 2 projects that are our real projects belong to one of our production solution file.
        // TryApplyChanges call will succeed on one project and will fail on the other.
        // When we try to run the code against the real production solution file(95 projects on it), it will fail a small few of projects while the
        // majority will succeed.
        string solutionPath = @"C:\work\ConsoleApplication5\ConsoleApplication5.sln";

        string dllPath1 = @"C:\docusign_source\SecTools\Code\CodeCoverage\CodeCoverageConfig\bin\Debug\Docusign.CodeCoverage.CodeCoverageConfig.dll";
        string dllPath2 = @"C:\docusign_source\Core\Platform\Monitoring\Monitoring.System\bin\Debug\Monitoring.System.dll";
        string dllName1 = "Docusign.CodeCoverage.CodeCoverageConfig.dll";
        string dllName2 = "Monitoring.System.dll";
        string name;
        bool containRef1, containRef2;
        bool changeApplied;
        Project project;
        Solution solution = workspace.OpenSolutionAsync(solutionPath).Result;
        Solution newSolution = solution;
        foreach (ProjectId projectId in solution.ProjectIds)
        {
            project = newSolution.GetProject(projectId);
            name = project.Name;
            if (!name.Equals(projName))
                continue;
            containRef1 = false;
            containRef2 = false;
            foreach (MetadataReference reference in project.MetadataReferences)
            {
                if (reference.Display.EndsWith(dllName1))
                {
                    containRef1 = true;
                }
                else if (reference.Display.EndsWith(dllName2))
                {
                    containRef2 = true;
                }

                if (containRef1 && containRef2)
                {
                    break;
                }
            }
            if (!containRef1)
            {
                project = project.AddMetadataReference(MetadataReference.CreateFromFile(dllPath1));
            }
            if (!containRef2)
            {
                project = project.AddMetadataReference(MetadataReference.CreateFromFile(dllPath2));
            }

            if (!(containRef1 && containRef2))
            {
                newSolution = project.Solution;
                //This call will fail for a small few projects of our production solution.
                changeApplied = workspace.TryApplyChanges(newSolution);
                if (!changeApplied)
                {
                    throw new ApplicationException(string.Format("TryApplyChanges on reference failed on {0}", name));
                }
            }
            Console.WriteLine("Project {0} done.", name);
        }
    }

}

}

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 27 (13 by maintainers)

Most upvoted comments

I just experienced this issue - very tricky to debug since there is zero detail in the TaskCancelledException. To figure it out I ran the compilation in a loop with a try / catch, each time it failed with this type of exception, I removed a metadata reference until the project got down to no metadata references. After this I looked at the projects ProjectReferences and noticed the failing project had duplicate references to a couple of the same projects. I opened the csproj and verified there were duplicate references. After fixing this the issue went away. I now use the following code to give me a better exception when this issue occurs:

var project = Solution.GetProject(id);
var dedupedProjectReferences = project.ProjectReferences.Select(x => x.ProjectId).Distinct().ToList();
if (dedupedProjectReferences.Count != project.ProjectReferences.Count()) {
    throw new Exception($"Project {id} cannot be compiled because it contains duplicate project references: {string.Join("|", project.ProjectReferences.Select(x => x.ProjectId))}");
}

Seems a little crazy to me that nothing does any validation that there is no duplicate project references (VS / MSBuild / Roslyn).

@cchamberlain You just saved me from pulling my hair out. I spent ages trying to work out what was wrong with this project and in the end it had duplicate keys.

Now I have another TaskCanceledException with no details as a result of a call to SymbolFinder.FindImplementationsAsync. Fantastic…