Skip to content

Commit

Permalink
Solution Restore should run in background
Browse files Browse the repository at this point in the history
Resolves NuGet/Home#3816.
Resolves NuGet/Home#4255.
Resolves NuGet/Home#4636.

In order to prevent hangs in VS Solution Restore should create a background task and push it in the restore worker queue.

Added E2E test suite for .NET Standard multi-targeting class library
  • Loading branch information
alpaix committed Mar 1, 2017
1 parent 215af32 commit 77fe4c0
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
using System.ComponentModel.Composition;
using System.ComponentModel.Design;
using System.Linq;
using System.Threading;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using NuGet.PackageManagement;
using NuGet.PackageManagement.UI;
using NuGet.PackageManagement.VisualStudio;
using NuGet.ProjectManagement;
using NuGetConsole;
using Task = System.Threading.Tasks.Task;

Expand Down Expand Up @@ -41,6 +41,8 @@ internal sealed class SolutionRestoreCommand
private readonly IVsMonitorSelection _vsMonitorSelection;
private uint _solutionNotBuildingAndNotDebuggingContextCookie;

private Task _restoreTask = Task.CompletedTask;

private SolutionRestoreCommand(
IMenuCommandService commandService,
IVsMonitorSelection vsMonitorSelection,
Expand Down Expand Up @@ -103,25 +105,23 @@ public static async Task InitializeAsync(AsyncPackage package)
/// <param name="e">Event args.</param>
private void OnRestorePackages(object sender, EventArgs args)
{
if (!SolutionRestoreWorker.IsBusy)
{
SolutionRestoreWorker.Restore(SolutionRestoreRequest.ByMenu());
}
else
if (_restoreTask.IsCompleted)
{
// QueryStatus should disable the context menu in most of the cases.
// Except when NuGetPackage was not loaded before VS won't send QueryStatus.
Logger.Log(MessageLevel.Info, Resources.SolutionRestoreFailed_RestoreWorkerIsBusy);
_restoreTask = NuGetUIThreadHelper.JoinableTaskFactory
.RunAsync(() => SolutionRestoreWorker.ScheduleRestoreAsync(
SolutionRestoreRequest.ByMenu(),
CancellationToken.None))
.Task;
}
}

private void BeforeQueryStatusForPackageRestore(object sender, EventArgs args)
{
NuGetUIThreadHelper.JoinableTaskFactory.Run((Func<Task>)async delegate
NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate
{
await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

OleMenuCommand command = (OleMenuCommand)sender;
var command = (OleMenuCommand)sender;

// Enable the 'Restore NuGet Packages' dialog menu
// - if the console is NOT busy executing a command, AND
Expand All @@ -130,10 +130,15 @@ private void BeforeQueryStatusForPackageRestore(object sender, EventArgs args)
// - if the solution is DPL enabled or there are NuGetProjects. This means that there loaded, supported projects
// Checking for DPL more is a temporary code until we've the capability to get nuget projects
// even in DPL mode. See https://github.com/NuGet/Home/issues/3711
command.Enabled = !ConsoleStatus.IsBusy &&
command.Enabled =
_restoreTask.IsCompleted &&
!ConsoleStatus.IsBusy &&
!SolutionRestoreWorker.IsBusy &&
IsSolutionExistsAndNotDebuggingAndNotBuilding() &&
(SolutionManager.IsSolutionDPLEnabled || Enumerable.Any<NuGetProject>(SolutionManager.GetNuGetProjects()));
(
SolutionManager.IsSolutionDPLEnabled ||
Enumerable.Any(SolutionManager.GetNuGetProjects())
);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,21 @@ private async Task<bool> StartBackgroundJobRunnerAsync(CancellationToken token)
while (!_pendingRequests.Value.IsCompleted
&& !token.IsCancellationRequested)
{
SolutionRestoreRequest discard;
if (!_pendingRequests.Value.TryTake(out discard, IdleTimeoutMs, token))
SolutionRestoreRequest next;
if (!_pendingRequests.Value.TryTake(out next, IdleTimeoutMs, token))
{
break;
}

// Upgrade request if necessary
if (next.RestoreSource != request.RestoreSource)
{
// there could be requests of two types: Auto-Restore or Explicit
// Explicit is always preferred.
request = new SolutionRestoreRequest(
next.ForceRestore || request.ForceRestore,
RestoreOperationSource.Explicit);
}
}

token.ThrowIfCancellationRequested();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace $safeprojectname$
{
public class Class1
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard1.4;net46</TargetFrameworks>
<PackageId>NuGet.TestPackage</PackageId>
<PackageVersion>1.0.1-preview</PackageVersion>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010">
<TemplateData>
<Name>NetStandardClassLibrary</Name>
<Description>.NET Standard class library template</Description>
<ProjectType>CSharp</ProjectType>
<SortOrder>1000</SortOrder>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>NetStandardClassLibrary</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
</TemplateData>
<TemplateContent>
<Project File="ClassLibrary.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" OpenInEditor="false">Class1.cs</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>
Loading

0 comments on commit 77fe4c0

Please sign in to comment.