简体   繁体   English

C# 后台任务取消异常

[英]C# exception on cancellation of background task

I have a simple HttpClient downloading solution where I need to support cancel download.我有一个简单的 HttpClient 下载解决方案,我需要支持取消下载。 Download itself works perfectly, however when I attempt to cancel download, I receive following exception:下载本身运行良好,但是当我尝试取消下载时,我收到以下异常:

Cannot access a disposed object.无法访问已处置的 object。 Object name: 'SslStream' Object 名称:'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?问题是,如何正确处理下载取消?

Add a try before any async call first, then,首先在任何异步调用之前添加一个尝试,然后,

Be sure to register a callback: cancellationToken.Register(client.CancelAsync);一定要注册一个回调:cancellationToken.Register(client.CancelAsync);

then when running the method await msg.Content.CopyToAsync(fs, cts.Token);然后在运行方法时等待 msg.Content.CopyToAsync(fs, cts.Token);

On the catch block you can handle the cancelation as follows:在 catch 块上,您可以按如下方式处理取消:

catch (WebException ex) when (ex.Status == WebExceptionStatus.RequestCanceled)
            {
                throw new OperationCanceledException();
            }               
            catch (TaskCanceledException)
            {
                throw new OperationCanceledException();
            }

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();
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM