Make long running tasks cancellable

This commit is contained in:
Jackson Schuster 2024-02-28 10:06:38 -08:00
parent b6fba7eb7c
commit 9ffe5c200d
3 changed files with 26 additions and 9 deletions

View file

@ -11,10 +11,10 @@ using System.Threading.Tasks;
public abstract class Archive : IDisposable
{
public static async Task<Archive> Create(string path)
public static async Task<Archive> Create(string path, CancellationToken cancellationToken = default)
{
if (path.EndsWith(".tar.gz"))
return await TarArchive.Create(path);
return await TarArchive.Create(path, cancellationToken);
else if (path.EndsWith(".zip"))
return ZipFileArchive.Create(path);
else
@ -40,7 +40,7 @@ public abstract class Archive : IDisposable
_extractedFolder = extractedFolder;
}
public static async Task<TarArchive> Create(string path, CancellationToken cancellationToken = default)
public static new async Task<TarArchive> Create(string path, CancellationToken cancellationToken = default)
{
var tmpFolder = Directory.CreateTempSubdirectory(nameof(FindArchiveDiffs));
using (var gzStream = File.OpenRead (path))
@ -90,7 +90,7 @@ public abstract class Archive : IDisposable
_archive = archive;
}
public static new ZipFileArchive Create(string path)
public static ZipFileArchive Create(string path)
{
return new ZipFileArchive(new ZipArchive(File.OpenRead(path)));
}

View file

@ -5,12 +5,13 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Task = System.Threading.Tasks.Task;
public class FindArchiveDiffs : Microsoft.Build.Utilities.Task
public class FindArchiveDiffs : Microsoft.Build.Utilities.Task, ICancelableTask
{
public class ArchiveItem
{
@ -26,6 +27,13 @@ public class FindArchiveDiffs : Microsoft.Build.Utilities.Task
[Output]
public ITaskItem[] ContentDifferences { get; set; } = [];
private CancellationTokenSource _cancellationTokenSource = new();
private CancellationToken cancellationToken => _cancellationTokenSource.Token;
public void Cancel()
{
_cancellationTokenSource.Cancel();
}
public override bool Execute()
{
return Task.Run(ExecuteAsync).Result;

View file

@ -4,10 +4,11 @@
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
public class GetClosestOfficialSdk : Microsoft.Build.Utilities.Task
public class GetClosestOfficialSdk : Microsoft.Build.Utilities.Task, ICancelableTask
{
[Required]
public required string BuiltSdkPath { get; init; }
@ -20,8 +21,16 @@ public class GetClosestOfficialSdk : Microsoft.Build.Utilities.Task
return Task.Run(ExecuteAsync).Result;
}
private CancellationTokenSource _cancellationTokenSource = new();
private CancellationToken cancellationToken => _cancellationTokenSource.Token;
public void Cancel()
{
_cancellationTokenSource.Cancel();
}
public async Task<bool> ExecuteAsync()
{
cancellationToken.ThrowIfCancellationRequested();
var (versionString, rid, extension) = Archive.GetInfoFromArchivePath(BuiltSdkPath);
string downloadUrl = GetLatestOfficialSdkUrl(versionString, rid, extension);
@ -32,14 +41,14 @@ public class GetClosestOfficialSdk : Microsoft.Build.Utilities.Task
AllowAutoRedirect = false
};
var client = new HttpClient(handler);
var redirectResponse = await client.GetAsync(downloadUrl);
var redirectResponse = await client.GetAsync(downloadUrl, cancellationToken);
// aka.ms returns a 301 for valid redirects and a 302 to Bing for invalid URLs
if (redirectResponse.StatusCode != HttpStatusCode.Moved)
{
Log.LogMessage(MessageImportance.High, $"Failed to download '{downloadUrl}': invalid aka.ms URL");
return true;
}
var packageResponse = await client.GetAsync(redirectResponse.Headers.Location!);
var packageResponse = await client.GetAsync(redirectResponse.Headers.Location!, cancellationToken);
var packageUriPath = packageResponse.RequestMessage!.RequestUri!.LocalPath;
string downloadedVersion = PathWithVersions.GetVersionInPath(packageUriPath).ToString();
@ -48,7 +57,7 @@ public class GetClosestOfficialSdk : Microsoft.Build.Utilities.Task
Log.LogMessage($"Copying {packageUriPath} to {ClosestOfficialSdkPath}");
using (var file = File.Create(ClosestOfficialSdkPath))
{
await packageResponse.Content.CopyToAsync(file);
await packageResponse.Content.CopyToAsync(file, cancellationToken);
}
return true;