c#取消已启动列表的任务<>

本文关键字:任务 列表 取消 启动 | 更新日期: 2023-09-27 18:03:43

我开始任务列表和等待任务。WhenAll

private async void btn_download_Click(object sender, EventArgs e)
    {
        .
        .
        .
        await DownloadMultipleFilesAsync(old_json);
        Console.WriteLine("Download completed.");
    }

这是我的代码,用list开始任务。

private async Task DownloadMultipleFilesAsync(List<media> doclist)
    {
        var token = cancelTokenSource.Token;
        await Task.WhenAll(doclist.Select(doc => DownloadFileAsync(doc)));
        btn_download.Enabled = true;
    }

和我的下载方法

private async Task DownloadFileAsync(media media)
{
    .
    .
    .
    Console.WriteLine(media.no + media_ext + " started.");
    webClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
    await webClient.DownloadFileTaskAsync(new Uri(media.url), @downloadToDirectory);
    Console.WriteLine(media.no + media_ext + " finished.");
    .
    .
    .
}

输出窗口如下:

1.jpg started.
2.jpg started.
3.jpg started.
4.jpg started.
5.jpg started.
6.jpg started.
7.jpg started.
8.jpg started.
9.jpg started.
10.jpg started.
11.jpg started.
12.jpg started.
13.jpg started.
14.jpg started.
15.jpg started.
16.jpg started.
17.jpg started.
18.jpg started.
19.jpg started.
1.jpg finished.
4.jpg finished.
2.jpg finished.
6.jpg finished.
8.jpg finished.
10.jpg finished.
3.jpg finished.
5.jpg finished.
12.jpg finished.
14.jpg finished.
7.jpg finished.
16.jpg finished.
18.jpg finished.
9.jpg finished.
11.jpg finished.
13.jpg finished.
15.jpg finished.
17.jpg finished.
19.jpg finished.
Download completed.

我想点击btn_cancel取消开始的任务,等待完成开始的任务。

private void btn_cancel_Click(object sender, EventArgs e)
{
    cancelTokenSource.Cancel();
    cancelTokenSource = new CancellationTokenSource();
}

c#取消已启动列表的任务<>

您需要做的是将取消令牌传递到调用链中,然后在可能的情况下使用它,您还需要注册一个取消回调以调用WebClient.CancelAsync()以取消下载。

private async void btn_download_Click(object sender, EventArgs e)
{
    .
    .
    .
    var token = cancelTokenSource.Token;
    try
    {
        await DownloadMultipleFilesAsync(old_json, token);
        Console.WriteLine("Download completed.");
    }
    catch(OperationCanceledException ex)
    {
        //If something other than our token caused the cancel bubble up the exception.
        if(ex.CancellationToken != token)
            throw;
    }
}

private async Task DownloadMultipleFilesAsync(List<media> doclist, CancellationToken token)
{
    await Task.WhenAll(doclist.Select(doc => DownloadFileAsync(doc, token));
    btn_download.Enabled = true;
}

private async Task DownloadFileAsync(media media, CancellationToken token)
{
    .
    .
    .
    Console.WriteLine(media.no + media_ext + " started.");
    webClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
    try
    {
        using(token.Register(() => webClient.CancelAsync()))
        {
            await webClient.DownloadFileTaskAsync(new Uri(media.url), @downloadToDirectory);
        }
    }            
    catch (WebException ex)
    {
        //Raise a OperationCanceledException if the request was canceled, otherwise bubble up the exception.
        if(ex.Status == WebExceptionStatus.RequestCanceled)
            throw new OperationCanceledException(token);
        else
            throw;
    }
    Console.WriteLine(media.no + media_ext + " finished.");
    .
    .
    .
}

WebClient不接受CancelationToken,这很奇怪。相反,它有一个方法CancelAsync,你可以调用它来取消挂起的调用。

似乎你必须保持一个引用你的webClient周围,并调用该方法点击取消按钮。