0

I am working on a small Visual Studio 2012 Add-in. The Add-in sets the reference path for all projects in the open solution. I am accomplishing this through a simple UI. Once the user enters their desired reference path string, a second window pops up that reports progress to the user.

For some reason,

proj.Properties.Item("ReferencePath").Value = referencePaths

takes a very long time to execute, so the UI is unresponsive. After learning this, I moved this item into an async method thinking that it would solve my problem.

The UI is still unresponsive and I cannot figure out why. Although I can drag the window around, and click the cancel button, these actions don't register until the above code completes (drag the window and it doesn't move until it goes on to the next operation). I have spent several hours reading C# textbooks and searching this site. Help is very appreciated! Also, feel free to comment on any other part of my code that could be improved.

Thanks!

public partial class FormWorking : Form
{
    CancellationTokenSource CancellationSource;

    public FormWorking()
    {
        InitializeComponent();
        CancellationSource = new CancellationTokenSource();
    }

    //progess is a Label object used to report progress.
    public string ProgressText
    {
        get { return progress.Text; }
        private set
        {
            progress.Text = value;
            if (progress.Width > this.Width - 2 * progress.Location.X)
            {
                this.Width = progress.Width + 2 * progress.Location.X;
            }
        }
    }

    //cancel event handler
    private void Cancel_Click(object sender, EventArgs e)
    {
        CancellationSource.Cancel();
    }

    //entry method for processing.  Adds paths to a solution in VS
    public void AddPaths(string referencePaths, Solution sln)
    {
        RecursiveAddPathsAsync(
            referencePaths,
            sln,
            new Progress<string>((Text) => ProgressText = Text)
            );
    }

    //recursive helper method
    async private void RecursiveAddPathsAsync(string referencePaths, Solution sln,
        IProgress<string> progressReporter)
    {
        try
        {
            foreach (Project proj in sln.Projects)
            {
                await RecurisveAddPathsAsync(referencePaths, proj, progressReporter, CancellationSource.Token);
            }
        }
        catch (OperationCanceledException) { }
    }

    //recursive method for project trees
    async private Task RecurisveAddPathsAsync(string referencePaths, Project proj,
        IProgress<string> progressReporter, CancellationToken cancelToken)
    {
        cancelToken.ThrowIfCancellationRequested();

        progressReporter.Report(proj.FullName);

        if (proj.FileName.EndsWith("csproj"))
        {
            try
            {
                //time consuming operation
                //the UI is unresponsive here!
                await Task.Run(
                    () => proj.Properties.Item("ReferencePath").Value = referencePaths
                    , cancelToken);
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                    throw;
            }
        }
        else
        {
            //recursion
            if (proj.ProjectItems != null)
                foreach (ProjectItem pi in proj.ProjectItems)
                    if (pi.SubProject != null)
                        await RecurisveAddPathsAsync(referencePaths, pi.SubProject,
                            progressReporter, cancelToken);
        }
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Brian
  • 1
  • COM objects like `Project` may marshal back to their STA (UI) thread. In that case, you may have to use a delay hack instead (`await Task.Delay(50)` periodically). – Stephen Cleary Oct 25 '14 at 10:40
  • @StephenCleary I don't quite understand how the `await Task.Delay` would help, but I am going to try the UI in another thread instead of the work being done in another thread. – Brian Oct 25 '14 at 21:04

0 Answers0