Search code examples
c#async-awaittaskhttpclientcancellation

C# exception on cancellation of background task


I have a simple HttpClient downloading solution where I need to support cancel download. Download itself works perfectly, however when I attempt to cancel download, I receive following exception:

Cannot access a disposed object. Object name: 'SslStream'

My code is the following:

var cts = new CancellationTokenSource();
var client = new HttpClient() { Timeout = TimeSpan.FromMinutes(5) };

DownloadButton.Click += async (s, e) => {
    var LocalPath = Path.Combine(AppContext.BaseDirectory, "index-5200-00.fits");
    if (!File.Exists(LocalPath)) {
        using (var fs = new FileStream(LocalPath, FileMode.Create, FileAccess.Write))
            using (var msg = await client.GetAsync(link1, cts.Token))
                await msg.Content.CopyToAsync(fs, cts.Token);
        Status = "Downloaded!";
    }
};

CancelButton.Click += (s, e) => {
    if (!cts.IsCancellationRequested) cts.Cancel();
};

Question is, how to properly handle the download cancellation?


Solution

  • I ended up with this code. It works exactly as expected:

    var cts = new CancellationTokenSource();
    var client = new HttpClient() { Timeout = TimeSpan.FromMinutes(5) };
    
    DownloadButton.Click += async (s, e) => {
        var LocalPath = Path.Combine(AppContext.BaseDirectory, "index-5200-00.fits");
        if (!File.Exists(LocalPath)) {
            try {
                using (var fs = new FileStream(LocalPath, FileMode.Create, FileAccess.Write))
                using (var stream = await client.GetStreamAsync(link1, cts.Token))
                    await stream.CopyToAsync(fs, cts.Token);
                Text = "Downloaded!";
            }
            catch (TaskCanceledException) {
                if (File.Exists(LocalPath)) File.Delete(LocalPath);
            }
            catch (Exception ex) {
                Text = ex.Message;
            }
        }
    };
    
    CancelButton.Click += (s, e) => {
        cts.Cancel();
    };